### Install erlang-term dependency Source: https://github.com/thomas9911/erlang-term/blob/master/README.md Add the erlang-term crate to your Cargo.toml file to include it in your Rust project. ```toml [dependencies] erlang-term = "1.1.0" ``` -------------------------------- ### Install erlang-term via Cargo Source: https://context7.com/thomas9911/erlang-term/llms.txt Configuration options for adding erlang-term to a Rust project's Cargo.toml file, including optional features for serde and zlib. ```toml [dependencies] erlang-term = "1.1.0" # With serde support for JSON conversion erlang-term = { version = "1.1.0", features = ["serde_impl"] } # With zlib compression support erlang-term = { version = "1.1.0", features = ["zlib"] } # With all features erlang-term = { version = "1.1.0", features = ["serde_impl", "zlib"] } ``` -------------------------------- ### Handle complex data structures Source: https://github.com/thomas9911/erlang-term/blob/master/README.md Example of mapping a complex Rust structure, such as a Map containing atoms and tuples, back into the Erlang binary format. ```rust use erlang_term::RawTerm; use std::iter::FromIterator; let map = RawTerm::Map(vec![ (RawTerm::SmallAtom(String::from("test")), RawTerm::SmallTuple(vec![RawTerm::SmallAtom(String::from("ok")), RawTerm::SmallInt(15)])), (RawTerm::SmallAtom(String::from("another_key")), RawTerm::Binary(b"this is a string".to_vec())), (RawTerm::SmallAtom(String::from("number")), RawTerm::Float(3.1415.into())), ]); let binary = vec![131, 116, 0, 0, 0, 3, 119, 4, 116, 101, 115, 116, 104, 2, 119, 2, 111, 107, 97, 15, 119, 11, 97, 110, 111, 116, 104, 101, 114, 95, 107, 101, 121, 109, 0, 0, 0, 16, 116, 104, 105, 115, 32, 105, 115, 32, 97, 32, 115, 116, 114, 105, 110, 103, 119, 6, 110, 117, 109, 98, 101, 114, 70, 64, 9, 33, 202, 192, 131, 18, 111]; assert_eq!(map.to_bytes(), binary); ``` -------------------------------- ### Serialize RawTerm to Erlang ETF Bytes in Rust Source: https://context7.com/thomas9911/erlang-term/llms.txt Illustrates converting `RawTerm` objects back into Erlang ETF byte format using the `RawTerm::to_bytes` method. This function provides a bijective conversion, ensuring that the original byte representation can be perfectly reconstructed. Examples include serializing maps, lists with improper tails, and other complex Erlang terms. ```rust use erlang_term::RawTerm; use std::iter::FromIterator; // Create and serialize a map with various types let map = RawTerm::Map(vec![ ( RawTerm::SmallAtom("test".to_string()), RawTerm::SmallTuple(vec![ RawTerm::SmallAtom("ok".to_string()), RawTerm::SmallInt(15), ]), ), ( RawTerm::SmallAtom("another_key".to_string()), RawTerm::Binary(b"this is a string".to_vec()), ), ( RawTerm::SmallAtom("number".to_string()), RawTerm::Float(3.1415.into()), ), ]); let bytes = map.to_bytes(); // bytes can be sent to Erlang/Elixir and decoded with :erlang.binary_to_term/1 // Verify round-trip preserves exact types let parsed = RawTerm::from_bytes(&bytes).expect("Failed to parse"); // parsed == map (exact type match) // Create a list with improper tail let improper_list = RawTerm::List(vec![ RawTerm::SmallInt(1), RawTerm::SmallInt(2), RawTerm::Improper(Box::new(RawTerm::SmallInt(3))), ]); let bytes = improper_list.to_bytes(); ``` -------------------------------- ### Read and Parse ETF Files in Rust Source: https://context7.com/thomas9911/erlang-term/llms.txt Demonstrates how to read binary ETF files from disk and parse them into either high-level Term or low-level RawTerm structures for processing. ```rust use erlang_term::{read_binary, Term, RawTerm}; // Read binary file containing ETF data let bytes = read_binary("path/to/erlang_term.bin") .expect("Failed to read file"); // Parse as high-level Term let term = Term::from_bytes(&bytes) .expect("Invalid ETF data"); // Or parse as RawTerm for more control let raw_term = RawTerm::from_bytes(&bytes) .expect("Invalid ETF data"); // Process the data match term { Term::List(items) => { for item in items { println!("Item: {}", item); } } Term::Map(map) => { for (key, value) in map { println!("{} => {}", key, value); } } _ => println!("Other: {:?}", term), } ``` -------------------------------- ### Configure optional features Source: https://github.com/thomas9911/erlang-term/blob/master/README.md Enable optional functionality like Serde integration for serialization or Zlib support for compressed ETF data. ```toml erlang-term = {version = "1.1.0", features = ["serde_impl"]} ``` ```toml erlang-term = {version = "1.1.0", features = ["zlib"]} ``` -------------------------------- ### Compressed ETF Serialization with zlib (Rust) Source: https://context7.com/thomas9911/erlang-term/llms.txt Enables zlib compression for serializing Erlang terms into ETF (Erlang Term) format, matching Elixir's `:erlang.term_to_binary/2` output with the `[:compressed]` option. This is useful for reducing the size of data transmitted over networks. The `zlib` feature must be enabled. ```rust // Requires: erlang-term = { version = "1.1.0", features = ["zlib"] } use erlang_term::{Term, RawTerm}; use flate2::Compression; // Create a term with repetitive data (compresses well) let list: Term = (0..100).map(Term::from).collect::>().into(); // Serialize with compression let compressed_bytes = list.to_gzip_bytes(Compression::new(6)) .expect("Compression failed"); // Compare sizes let uncompressed_bytes = list.clone().to_bytes(); println!("Uncompressed: {} bytes", uncompressed_bytes.len()); println!("Compressed: {} bytes", compressed_bytes.len()); // Decompress and parse (automatic when parsing) let parsed = Term::from_bytes(&compressed_bytes) .expect("Failed to parse compressed ETF"); // Using RawTerm for compression let raw_list = RawTerm::List((0..100).map(RawTerm::Int).collect()); let compressed = raw_list.to_gzip_bytes(Compression::default()) .expect("Compression failed"); // The compressed format is compatible with Erlang/Elixir: // iex> :erlang.binary_to_term(compressed_bytes) ``` -------------------------------- ### Serde JSON Integration for Erlang Terms (Rust) Source: https://context7.com/thomas9911/erlang-term/llms.txt Provides serialization and deserialization between Erlang `Term` and JSON using the `serde` and `serde_json` crates. This integration is enabled by the `serde_impl` feature and is useful for web APIs and configuration files. It allows easy conversion of data structures between these formats. ```rust // Requires: erlang-term = { version = "1.1.0", features = ["serde_impl"] } use erlang_term::{Term, RawTerm}; use serde_json; // Parse JSON into Term let json_input = r#"{ "number": 1, "float": 3.14, "list": [1, 2, 3, 4, {"nested": "true"}], "map": {"test": 123456}, "string": "testing", "boolean": true, "none": null }"#; let json_value: serde_json::Value = serde_json::from_str(json_input) .expect("Invalid JSON"); let term: Term = serde_json::from_value(json_value.clone()) .expect("Failed to convert to Term"); // Convert Term to ETF bytes let raw_term = RawTerm::from(term); let etf_bytes = raw_term.to_bytes(); // Send to Erlang/Elixir system... // iex> :erlang.binary_to_term(etf_bytes) // Convert ETF back to JSON let parsed_raw = RawTerm::from_bytes(&etf_bytes).expect("Invalid ETF"); let parsed_term = Term::from(parsed_raw); let output_json = serde_json::to_value(&parsed_term) .expect("Failed to serialize to JSON"); // Round-trip preserved assert_eq!(json_value, output_json); // Pretty print JSON from ETF let term = Term::from_bytes(&etf_bytes).expect("Invalid ETF"); let pretty_json = serde_json::to_string_pretty(&term) .expect("Failed to serialize"); println!("{}", pretty_json); ``` -------------------------------- ### Convert Rust types to Erlang Terms Source: https://context7.com/thomas9911/erlang-term/llms.txt Demonstrates the use of the From trait to convert native Rust primitives, collections, and tuples into Erlang Term types. This supports integers, floats, strings, vectors, HashMaps, and keyword lists. ```rust use erlang_term::Term; use std::collections::HashMap; // Primitives let byte_term: Term = 42u8.into(); let int_term: Term = 12345i32.into(); let float_term: Term = 3.14f64.into(); let bool_term: Term = true.into(); let nil_term: Term = ().into(); // Strings let string_term: Term = "hello".into(); // Tuples and Lists let tuple2: Term = (1, "test").into(); let list: Term = vec!["one", "two", "three"].into(); // Maps and Keyword lists let mut map = HashMap::new(); map.insert("key1", 100); let map_term: Term = map.into(); let keyword: Term = vec![("key1", 1), ("key2", 2)].into(); ``` -------------------------------- ### Convert Erlang External Term Format to Rust objects Source: https://github.com/thomas9911/erlang-term/blob/master/README.md Demonstrates converting binary data into Rust structures using Term or RawTerm enums. Term provides a higher-level interface, while RawTerm maps directly to the external term format specification. ```rust use erlang_term::Term; let input = &[131, 107, 0, 4, 1, 2, 3, 4]; let term = Term::from_bytes(input); assert_eq!(Ok(Term::Charlist([1, 2, 3, 4].to_vec())), term); ``` ```rust use erlang_term::RawTerm; let input = &[131, 107, 0, 4, 1, 2, 3, 4]; let term = RawTerm::from_bytes(input); assert_eq!(Ok(RawTerm::String([1, 2, 3, 4].to_vec())), term); ``` -------------------------------- ### Inspecting Raw Erlang Terms Source: https://context7.com/thomas9911/erlang-term/llms.txt Utilizes RawTerm for low-level inspection of Erlang term structures. It provides methods to identify exact types and general categories, which is useful for implementing Erlang-compliant term ordering. ```rust use erlang_term::RawTerm; use erlang_term::raw_term::{RawTermType, RawTermGeneralType}; let term = RawTerm::SmallAtom("test".to_string()); // Exact type and category checking let term_type = term.as_type(); let general_type = term.as_general_type(); // Check for specific structures like keyword-list-style tuples let pair = RawTerm::SmallTuple(vec![RawTerm::SmallAtom("key".to_string()), RawTerm::SmallInt(42)]); assert!(pair.is_atom_pair()); ``` -------------------------------- ### Serialize Term objects to ETF bytes Source: https://context7.com/thomas9911/erlang-term/llms.txt Demonstrates using Term::to_bytes to serialize Rust Term objects back into Erlang External Term Format. This supports round-trip data conversion for interoperability. ```rust use erlang_term::Term; use std::collections::HashMap; // Convert a simple integer to bytes let term = Term::Int(12345); let bytes = term.to_bytes(); assert_eq!(bytes, vec![131, 98, 0, 0, 48, 57]); // Convert a string to ETF binary format let term = Term::String("testing".to_string()); let bytes = term.to_bytes(); // Create and serialize a complex map let mut map = HashMap::new(); map.insert(Term::Atom("status".to_string()), Term::Atom("ok".to_string())); map.insert(Term::Atom("count".to_string()), Term::Int(42)); let term = Term::Map(map); let bytes = term.to_bytes(); // Round-trip example let original = Term::Tuple(vec![ Term::Atom("response".to_string()), Term::Int(200), Term::String("Success".to_string()), ]); let bytes = original.clone().to_bytes(); let parsed = Term::from_bytes(&bytes).expect("Failed to parse"); ``` -------------------------------- ### Display Erlang Terms in Elixir Syntax (Rust) Source: https://context7.com/thomas9911/erlang-term/llms.txt Implements the `Display` trait for `Term` to print Erlang/Elixir data in a familiar Elixir-like syntax. This is useful for debugging and logging. It handles various term types including atoms, strings, lists, tuples, maps, keyword lists, and bytes. ```rust use erlang_term::Term; use erlang_term::term::print_elixir_term; use keylist::Keylist; use std::collections::HashMap; // Atoms let atom = Term::Atom("my_atom".to_string()); println!("{}", atom); // Output: :my_atom // Module-style atoms (capitalized) let module = Term::Atom("MyModule".to_string()); println!("{}", module); // Output: MyModule // Strings let string = Term::String("hello world".to_string()); println!("{}", string); // Output: "hello world" // Lists let list = Term::List(vec![Term::Int(1), Term::Int(2), Term::Int(3)]); println!("{}", list); // Output: [1, 2, 3] // Tuples let tuple = Term::Tuple(vec![ Term::Atom("ok".to_string()), Term::Int(42), ]); println!("{}", tuple); // Output: {:ok, 42} // Maps let mut map = HashMap::new(); map.insert(Term::Atom("key".to_string()), Term::Int(100)); let map_term = Term::Map(map); println!("{}", map_term); // Output: %{:key => 100} // Keyword lists let mut keylist = Keylist::new(); keylist.push("name".to_string(), Term::String("Alice".to_string())); keylist.push("age".to_string(), Term::Int(30)); let keyword = Term::Keyword(keylist); println!("{}", keyword); // Output: [name: "Alice", age: 30] // Bytes (binary) let bytes = Term::Bytes(vec![1, 2, 3, 4]); println!("{}", bytes); // Output: <<1, 2, 3, 4>> ``` -------------------------------- ### Parse Erlang ETF Bytes to RawTerm in Rust Source: https://context7.com/thomas9911/erlang-term/llms.txt Demonstrates parsing various Erlang ETF byte sequences into `RawTerm` objects using the `RawTerm::from_bytes` function. This method is useful for preserving precise Erlang type information, including different atom encodings, charlists as strings, small integers, regular integers, and floats. ```rust use erlang_term::RawTerm; // Parse a charlist - RawTerm preserves it as String type (Erlang's string) let input = &[131, 107, 0, 4, 1, 2, 3, 4]; let raw_term = RawTerm::from_bytes(input).expect("Failed to parse"); assert_eq!(raw_term, RawTerm::String(vec![1, 2, 3, 4])); // Parse a small integer (0-255) let small_int = &[131, 97, 42]; let raw_term = RawTerm::from_bytes(small_int).expect("Failed to parse"); assert_eq!(raw_term, RawTerm::SmallInt(42)); // Parse a regular integer let int_bytes = &[131, 98, 255, 255, 255, 243]; // -13 let raw_term = RawTerm::from_bytes(int_bytes).expect("Failed to parse"); assert_eq!(raw_term, RawTerm::Int(-13)); // Parse a float let float_bytes = &[131, 70, 64, 9, 33, 202, 192, 131, 18, 111]; // 3.1415 let raw_term = RawTerm::from_bytes(float_bytes).expect("Failed to parse"); // RawTerm::Float uses OrderedFloat for hashing support // Parse and distinguish between different atom encodings let small_atom = &[131, 119, 4, 116, 101, 115, 116]; // SmallAtom "test" let raw_term = RawTerm::from_bytes(small_atom).expect("Failed to parse"); assert_eq!(raw_term, RawTerm::SmallAtom("test".to_string())); ``` -------------------------------- ### Format Erlang Terms as Elixir Syntax Source: https://github.com/thomas9911/erlang-term/blob/master/TODO.md Converts internal Erlang term representations into human-readable Elixir syntax. Specifically handles tuple formatting, such as transforming byte sequences into standard Elixir tuple notation. ```elixir defimpl String.Chars, for: ErlangTerm do def to_string(term) do # Example: Tuple([Byte(1), Byte(2), Byte(3)]) -> {1, 2, 3} "{#{Enum.join(term.values, ",")}}" end end ``` -------------------------------- ### Type Checking and Extracting Term Values Source: https://context7.com/thomas9911/erlang-term/llms.txt Shows how to validate the type of a Term using is_* methods and safely extract inner values using as_* methods. These extraction methods consume the term and return an Option. ```rust use erlang_term::Term; let term = Term::Atom("example".to_string()); // Type checking assert!(term.is_atom()); // Extraction (consumes the term) let atom_value = term.as_atom(); assert_eq!(atom_value, Some("example".to_string())); // Working with maps if let Some(string_map) = map_term.as_string_map() { assert_eq!(string_map.get("key"), Some(&Term::Int(100))); } ``` -------------------------------- ### Add Integration Test Dependency in Mix.exs Source: https://github.com/thomas9911/erlang-term/blob/master/integration_test/README.md This code snippet shows how to add the 'integration_test' package as a dependency in your Elixir project's mix.exs file. Ensure you are using a compatible version, such as '~> 0.1.0'. This is a standard practice for managing project dependencies in Elixir. ```elixir def deps do [ {:integration_test, "~> 0.1.0"} ] end ``` -------------------------------- ### GZIP Compression for Erlang Terms Source: https://github.com/thomas9911/erlang-term/blob/master/TODO.md Provides functionality to compress and decompress Erlang terms using GZIP. This is useful for reducing the storage footprint of serialized Erlang data structures. ```erlang %% GZIP from binary term_to_binary(Term, [compressed]). %% GZIP to binary binary_to_term(CompressedBinary). ``` -------------------------------- ### Integrate Erlang Terms with Rust via Rustler Source: https://github.com/thomas9911/erlang-term/blob/master/TODO.md Configures the bridge between Erlang/Elixir and Rust using the Rustler library. This allows for high-performance manipulation of Erlang terms within a Rust environment. ```rust #[rustler::nif] fn process_term(term: rustler::Term) -> rustler::Term { // Logic to interface with Erlang terms term } ``` -------------------------------- ### Convert Between Term and RawTerm in Rust Source: https://context7.com/thomas9911/erlang-term/llms.txt Shows how to convert between `Term` and `RawTerm` types in Rust. Converting from `RawTerm` to `Term` applies Elixir semantics, normalizing atoms like 'true', 'false', and 'nil' to their boolean or nil equivalents, and detecting keyword lists. Converting from `Term` to `RawTerm` may result in some type information loss, as certain `Term` types are represented differently in `RawTerm` (e.g., booleans become atoms). ```rust use erlang_term::{Term, RawTerm}; // RawTerm to Term - applies Elixir semantics let raw = RawTerm::Binary(vec![116, 101, 115, 116, 105, 110, 103]); // "testing" let term = Term::from(raw); assert_eq!(term.as_string(), Some("testing".to_string())); // Atoms "true", "false", "nil" become Term::Bool or Term::Nil let raw_true = RawTerm::AtomDeprecated("true".to_string()); let term = Term::from(raw_true); assert_eq!(term, Term::Bool(true)); let raw_nil = RawTerm::SmallAtom("nil".to_string()); let term = Term::from(raw_nil); assert_eq!(term, Term::Nil); // Term to RawTerm let term = Term::String("hello".to_string()); let raw = RawTerm::from(term); assert_eq!(raw, RawTerm::Binary(b"hello".to_vec())); // Booleans become SmallAtom let term = Term::Bool(false); let raw = RawTerm::from(term); assert_eq!(raw, RawTerm::SmallAtom("false".to_string())); // Complex conversion: keyword lists let raw_keyword = RawTerm::List(vec![ RawTerm::SmallTuple(vec![ RawTerm::AtomDeprecated("key1".to_string()), RawTerm::SmallInt(1), ]), RawTerm::SmallTuple(vec![ RawTerm::AtomDeprecated("key2".to_string()), RawTerm::SmallInt(2), ]), ]); let term = Term::from(raw_keyword); // term is now Term::Keyword with Keylist structure ``` -------------------------------- ### Parse ETF bytes into Term objects Source: https://context7.com/thomas9911/erlang-term/llms.txt Demonstrates using Term::from_bytes to convert Erlang External Term Format byte slices into high-level Rust Term enums. This handles various types including charlists, integers, strings, and tuples. ```rust use erlang_term::Term; // Parse a simple charlist [1,2,3,4] from Elixir's :erlang.term_to_binary([1,2,3,4]) let input = &[131, 107, 0, 4, 1, 2, 3, 4]; let term = Term::from_bytes(input).expect("Failed to parse ETF"); assert_eq!(term, Term::Charlist(vec![1, 2, 3, 4])); // Parse an integer let int_bytes = &[131, 98, 0, 1, 226, 64]; // 123456 in ETF let term = Term::from_bytes(int_bytes).expect("Failed to parse"); assert_eq!(term, Term::Int(123456)); // Parse a string (binary in Erlang) let string_bytes = &[131, 109, 0, 0, 0, 5, 104, 101, 108, 108, 111]; // "hello" let term = Term::from_bytes(string_bytes).expect("Failed to parse"); assert_eq!(term, Term::String("hello".to_string())); // Parse a tuple let tuple_bytes = &[131, 104, 2, 119, 2, 111, 107, 97, 42]; // {:ok, 42} let term = Term::from_bytes(tuple_bytes).expect("Failed to parse"); if let Term::Tuple(elements) = term { assert_eq!(elements.len(), 2); assert_eq!(elements[0], Term::Atom("ok".to_string())); assert_eq!(elements[1], Term::Byte(42)); } ``` -------------------------------- ### Filter Non-Data Terms in Rust Source: https://context7.com/thomas9911/erlang-term/llms.txt Provides a recursive function to filter out Erlang-specific types like PIDs, references, and functions from a RawTerm structure, leaving only pure data types. ```rust use erlang_term::{RawTerm, Term}; fn filter_data_only(term: RawTerm) -> Option { match term { RawTerm::SmallInt(_) | RawTerm::Int(_) | RawTerm::Float(_) | RawTerm::Binary(_) | RawTerm::String(_) | RawTerm::Nil | RawTerm::Atom(_) | RawTerm::SmallAtom(_) | RawTerm::AtomDeprecated(_) | RawTerm::SmallAtomDeprecated(_) | RawTerm::SmallBigInt(_) | RawTerm::LargeBigInt(_) => Some(term), RawTerm::List(items) => { let filtered: Vec<_> = items.into_iter().filter_map(filter_data_only).collect(); Some(RawTerm::List(filtered)) } RawTerm::SmallTuple(items) => { let filtered: Vec<_> = items.into_iter().map(|t| filter_data_only(t).unwrap_or(RawTerm::Nil)).collect(); Some(RawTerm::SmallTuple(filtered)) } RawTerm::Map(pairs) => { let filtered: Vec<_> = pairs.into_iter().filter_map(|(k, v)| { Some((filter_data_only(k)?, filter_data_only(v)?)) }).collect(); Some(RawTerm::Map(filtered)) } RawTerm::Pid { .. } | RawTerm::NewPid { .. } | RawTerm::Port { .. } | RawTerm::NewPort { .. } | RawTerm::Ref { .. } | RawTerm::NewerRef { .. } | RawTerm::Function { .. } => None, _ => None, } } // Usage let etf_bytes: &[u8] = &[/* ETF data with PIDs/refs */]; let raw_term = RawTerm::from_bytes(etf_bytes).expect("Invalid ETF"); if let Some(filtered) = filter_data_only(raw_term) { let clean_bytes = filtered.to_bytes(); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.