### Generate PHP Serialized Output Source: https://github.com/nickbabcock/phpserz/blob/master/README.md Example of creating a PHP class and serializing it to the PHP serialization format. This is useful for understanding the output format that PHPserz can parse. ```php 12345, "tags" => ["php", "rust", "serialization"] ]; } $example = new Example(); $serialized = serialize($example); echo $serialized; ?> ``` -------------------------------- ### Structured Error Handling with PhpParser Source: https://context7.com/nickbabcock/phpserz/llms.txt Demonstrates how to use `PhpParser` and its `Error`/`ErrorKind` types for structured error handling, including identifying unexpected bytes, EOF conditions, and integer overflows. ```rust use phpserz::{PhpParser, Error, ErrorKind}; // UnexpectedByte with position let mut parser = PhpParser::new(b"x:invalid;"); let err = parser.next_token().unwrap_err(); assert!(matches!( err.kind(), ErrorKind::UnexpectedByte { found: b'x', position: 0 } )); println!("{err}"); // "Unexpected byte 'x' at position: 0" // Eof when input is truncated let mut parser = PhpParser::new(b"s:10:\"hello\";"); // length says 10, only 5 bytes let err = parser.next_token().unwrap_err(); assert!(matches!(err.kind(), ErrorKind::Eof)); assert_eq!(err.position(), None); // Overflow on integer out of i64 range let mut parser = PhpParser::new(b"i:9223372036854775808;"); // i64::MAX + 1 let err = parser.next_token().unwrap_err(); assert!(matches!(err.kind(), ErrorKind::Overflow { .. })); println!("overflow at byte {}", err.position().unwrap()); ``` -------------------------------- ### Add PHPserz to Cargo.toml Source: https://context7.com/nickbabcock/phpserz/llms.txt Include the phpserz crate in your project's dependencies. Serde support is enabled by default. Disable it if only the low-level parser is needed. ```toml [dependencies] phpserz = "0.3.0" # serde support enabled by default # Disable serde if you only need the low-level parser # phpserz = { version = "0.3.0", default-features = false } ``` -------------------------------- ### PhpDeserializer::from_parser / PhpDeserializer::into_parser Source: https://context7.com/nickbabcock/phpserz/llms.txt Allows interoperability between `PhpDeserializer` and `PhpParser`. A `PhpDeserializer` can be created from an existing `PhpParser` to continue deserialization with serde, and the parser can be reclaimed later to resume manual token processing. ```APIDOC ## PhpDeserializer::from_parser / PhpDeserializer::into_parser ### Description Allows interoperability between `PhpDeserializer` and `PhpParser`. A `PhpDeserializer` can be created from an existing `PhpParser` to continue deserialization with serde, and the parser can be reclaimed later to resume manual token processing. ### Method - `PhpDeserializer::from_parser(parser: PhpParser<'_>) -> PhpDeserializer<'_>` - `PhpDeserializer::into_parser(self) -> PhpParser<'_>` ### Parameters - **parser** (`PhpParser<'_>`) - An instance of `PhpParser` from which to create the `PhpDeserializer`. ### Request Example ```rust use phpserz::{PhpDeserializer, PhpParser}; let input = b"i:42;s:5:\"hello\";"; let mut parser = PhpParser::new(input); // Manually consume a token parser.next_token().unwrap(); // Create a deserializer from the parser let mut de = PhpDeserializer::from_parser(parser); let s: String = de.deserialize().unwrap(); // Deserializes "hello" // Reclaim the parser let mut parser = de.into_parser(); // Continue manual parsing with the reclaimed parser ``` ### Response #### Success Response - `PhpDeserializer` instance (from `from_parser`) - `PhpParser` instance (from `into_parser`) #### Response Example (Instance of `PhpDeserializer` or `PhpParser`) ``` -------------------------------- ### PhpDeserializer::new Source: https://context7.com/nickbabcock/phpserz/llms.txt Creates a `PhpDeserializer` instance from raw bytes, enabling direct mapping of PHP-serialized data to Rust structs that derive `serde::Deserialize`. It automatically handles PHP visibility prefixes for object properties. ```APIDOC ## PhpDeserializer::new ### Description Creates a `PhpDeserializer` instance from raw bytes, enabling direct mapping of PHP-serialized data to Rust structs that derive `serde::Deserialize`. It automatically handles PHP visibility prefixes for object properties. ### Method `PhpDeserializer::new(serialized_bytes: &[u8]) -> PhpDeserializer<'_>` ### Parameters - **serialized_bytes** (&[u8]) - The raw byte slice containing PHP-serialized data. ### Request Example ```rust use phpserz::PhpDeserializer; use serde::Deserialize; #[derive(Deserialize)] struct MyData { field: String, } let serialized_data = b"s:5:\"hello\";"; // PHP: serialize("hello") let mut deserializer = PhpDeserializer::new(serialized_data); let data: MyData = deserializer.deserialize().unwrap(); ``` ### Response #### Success Response A `PhpDeserializer` instance ready for deserialization. #### Response Example (Instance of `PhpDeserializer`) ``` -------------------------------- ### Deserialize PHP Data with Serde Source: https://github.com/nickbabcock/phpserz/blob/master/README.md Demonstrates deserializing PHP serialized data into Rust structs using the `serde` feature of the PHPserz crate. Ensure the `serde` feature is enabled. ```rust #[cfg(feature = "serde")] { use phpserz::PhpDeserializer; use serde::Deserialize; use std::collections::BTreeMap; #[derive(Debug, Deserialize, PartialEq)] struct Example { name: String, age: i32, #[serde(rename = "isActive")] is_active: bool, scores: BTreeMap, metadata: Metadata, } #[derive(Debug, Deserialize, PartialEq)] struct Metadata { id: i32, tags: BTreeMap, } let serialized = b"O:7:\"Example\":5:{s:4:\"name\";s:8:\"John Doe\";s:12:\"\0Example\0age\";i:42;s:11:\"\0*\0isActive\";b:1;s:6:\"scores\";a:3:{i:0;d:95.5;i:1;d:88.0;i:2;d:92.3;}s:8:\"metadata\";a:2:{s:2:\"id\";i:12345;s:4:\"tags\";a:3:{i:0;s:3:\"php\";i:1;s:4:\"rust\";i:2;s:13:\"serialization\";}}}"; let mut deserializer = PhpDeserializer::new(serialized); let example = Example::deserialize(&mut deserializer).unwrap(); assert_eq!( example, Example { name: "John Doe".to_string(), age: 42, is_active: true, scores: BTreeMap::from([ (0, 95.5), (1, 88.0), (2, 92.3), ]), metadata: Metadata { id: 12345, tags: BTreeMap::from([ (0, "php".to_string()), (1, "rust".to_string()), (2, "serialization".to_string()) ]), } } ); } ``` -------------------------------- ### Deserialize PHP Arrays to Rust Vec and HashMap Source: https://context7.com/nickbabcock/phpserz/llms.txt Demonstrates deserializing dense integer-keyed PHP arrays into Rust Vec and associative arrays into HashMap. Sparse integer-keyed arrays will result in an error when targeting Vec. ```rust use phpserz::PhpDeserializer; use serde::Deserialize; use std::collections::HashMap; // Dense integer array → Vec let input = b"a:3:{i:0;s:2:\"aa\";i:1;s:2:\"bb\";i:2;s:2:\"cc\";}"; let result: Vec = Deserialize::deserialize(&mut PhpDeserializer::new(input)).unwrap(); assert_eq!(result, ["aa", "bb", "cc"]); // Associative array → HashMap let input = b"a:2:{s:3:\"foo\";s:3:\"bar\";s:3:\"baz\";s:3:\"qux\";}"; let result: HashMap = Deserialize::deserialize(&mut PhpDeserializer::new(input)).unwrap(); assert_eq!(result["foo"], "bar"); // Sparse integer array → error let sparse = b"a:2:{i:1;s:2:\"aa\";i:3;s:2:\"bb\";}"; let err: Result, _> = Deserialize::deserialize(&mut PhpDeserializer::new(sparse)); assert!(err.is_err()); // "Expected sequence index 0, found integer key 1" ``` -------------------------------- ### Interop between PhpDeserializer and PhpParser Source: https://context7.com/nickbabcock/phpserz/llms.txt Construct a `PhpDeserializer` from an existing `PhpParser` to preserve its cursor position, or convert a `PhpDeserializer` back into a `PhpParser`. This enables mixed manual and serde-based parsing workflows. ```rust use phpserz::{PhpDeserializer, PhpParser, PhpToken}; use serde::Deserialize; let input = b"i:42;s:5:\"hello\";b:1;"; let mut parser = PhpParser::new(input); // Manually consume the first token assert_eq!(parser.next_token().unwrap(), Some(PhpToken::Integer(42))); // Hand off remaining input to serde let mut de = PhpDeserializer::from_parser(parser); let s: String = Deserialize::deserialize(&mut de).unwrap(); assert_eq!(s, "hello"); // Reclaim the parser and keep reading manually let mut parser = de.into_parser(); assert_eq!(parser.next_token().unwrap(), Some(PhpToken::Boolean(true))); assert_eq!(parser.next_token().unwrap(), None); // end of input ``` -------------------------------- ### Stream PHP tokens with PhpParser Source: https://context7.com/nickbabcock/phpserz/llms.txt Use `PhpParser` for zero-copy streaming of `PhpToken` variants from raw bytes. String content is returned as `PhpBstr` slices without heap allocation. The caller manages iteration and container depth. ```rust use phpserz::{PhpParser, PhpToken, PhpBstr}; // PHP: array(0 => "foo", 1 => "bar") let input = b"a:2:{i:0;s:3:\"foo\";i:1;s:3:\"bar\";}"; let mut parser = PhpParser::new(input); let tokens: Vec> = std::iter::from_fn(|| parser.next_token().unwrap()).collect(); assert_eq!(tokens, vec![ PhpToken::Array { elements: 2 }, PhpToken::Integer(0), PhpToken::String(PhpBstr::new(b"foo")), PhpToken::Integer(1), PhpToken::String(PhpBstr::new(b"bar")), PhpToken::End, ]); ``` -------------------------------- ### Manual PHP Token Parsing Source: https://github.com/nickbabcock/phpserz/blob/master/README.md Provides a lower-level interface for parsing PHP serialized data by reading individual tokens. This is useful for inspecting the data structure or implementing custom deserialization logic. ```rust use phpserz::{Error, PhpParser, PhpToken, PhpBstr, PhpVisibility}; let serialized = b"O:7:\"Example\":5:{s:4:\"name\";s:8:\"John Doe\";s:12:\"\0Example\0age\";i:42;s:11:\"\0*\0isActive\";b:1;s:6:\"scores\";a:3:{i:0;d:95.5;i:1;d:88.0;i:2;d:92.3;}s:8:\"metadata\";a:2:{s:2:\"id\";i:12345;s:4:\"tags\";a:3:{i:0;s:3:\"php\";i:1;s:4:\"rust\";i:2;s:13:\"serialization\";}}}"; let mut parser = PhpParser::new(&serialized[..]); assert_eq!( parser.read_token().unwrap(), PhpToken::Object { class: PhpBstr::new(b"Example"), properties: 5 } ); let PhpToken::String(prop) = parser.read_token().unwrap() else { panic!("Expected a string token"); }; assert_eq!(prop, PhpBstr::new(b"name")); let prop = prop.to_property(); assert_eq!(prop.to_str().unwrap(), "name"); assert_eq!(prop.visibility(), PhpVisibility::Public); // ... ``` -------------------------------- ### Deserialize PHP Strings and Arrays to Rust Enums Source: https://context7.com/nickbabcock/phpserz/llms.txt Shows how PHP strings map to Rust unit enums, and how externally or internally tagged enums are deserialized. Supports unit variants from PHP strings or single-entry arrays. ```rust use phpserz::PhpDeserializer; use serde::Deserialize; #[derive(Debug, Deserialize, PartialEq)] enum Direction { North, South, } #[derive(Debug, Deserialize, PartialEq)] enum Message { Text(String), Number(i32), } #[derive(Debug, Deserialize, PartialEq)] enum Shape { Point(i32, i32), } // Unit variant from PHP string let input = b"s:5:\"North\";"; let d: Direction = Deserialize::deserialize(&mut PhpDeserializer::new(input)).unwrap(); assert_eq!(d, Direction::North); // Newtype variant from single-entry PHP array let input = b"a:1:{s:4:\"Text\";s:5:\"Hello\";}"; let m: Message = Deserialize::deserialize(&mut PhpDeserializer::new(input)).unwrap(); assert_eq!(m, Message::Text("Hello".to_string())); // Tuple variant let input = b"a:1:{s:5:\"Point\";a:2:{i:0;i:3;i:1;i:4;}}"; let s: Shape = Deserialize::deserialize(&mut PhpDeserializer::new(input)).unwrap(); assert_eq!(s, Shape::Point(3, 4)); // Unit variant as single-entry PHP array with null payload let input = b"a:1:{s:5:\"North\";N;}"; let d: Direction = Deserialize::deserialize(&mut PhpDeserializer::new(input)).unwrap(); assert_eq!(d, Direction::North); ``` -------------------------------- ### PhpBstr: Handling PHP Byte Strings and Properties Source: https://context7.com/nickbabcock/phpserz/llms.txt `PhpBstr` wraps borrowed byte slices. Use `to_str()` for UTF-8 decoding and `to_property()` to extract property names and visibility. ```rust use phpserz::{PhpBstr, PhpVisibility}; // Public property — no prefix let bstr = PhpBstr::new(b"username"); let prop = bstr.to_property(); assert_eq!(prop.to_str().unwrap(), "username"); assert_eq!(prop.visibility(), PhpVisibility::Public); // Private property — prefix: \0ClassName\0 let bstr = PhpBstr::new(b"\0MyClass\0secretField"); let prop = bstr.to_property(); assert_eq!(prop.to_str().unwrap(), "secretField"); assert_eq!(prop.visibility(), PhpVisibility::Private); // Protected property — prefix: \0*\0 let bstr = PhpBstr::new(b"\0*\0protectedVar"); let prop = bstr.to_property(); assert_eq!(prop.to_str().unwrap(), "protectedVar"); assert_eq!(prop.visibility(), PhpVisibility::Protected); // Raw bytes access (no UTF-8 check) assert_eq!(bstr.as_bytes(), b"\0*\0protectedVar"); ``` -------------------------------- ### PhpParser::new / PhpParser::next_token Source: https://context7.com/nickbabcock/phpserz/llms.txt Provides a low-level, zero-copy streaming interface for parsing PHP-serialized data. It yields `PhpToken` variants sequentially without intermediate allocations, allowing fine-grained control over the parsing process. ```APIDOC ## PhpParser::new / PhpParser::next_token ### Description Provides a low-level, zero-copy streaming interface for parsing PHP-serialized data. It yields `PhpToken` variants sequentially without intermediate allocations, allowing fine-grained control over the parsing process. ### Method - `PhpParser::new(input: &[u8]) -> PhpParser<'_>` - `PhpParser::next_token(&mut self) -> Result>, Error>` ### Parameters - **input** (&[u8]) - The raw byte slice containing PHP-serialized data. ### Request Example ```rust use phpserz::{PhpParser, PhpToken, PhpBstr}; let input = b"a:2:{i:0;s:3:\"foo\";}"; // PHP: array("foo") let mut parser = PhpParser::new(input); loop { match parser.next_token() { Ok(Some(token)) => { println!("{:?}", token); if token == PhpToken::End { break; } } Ok(None) => break, // Should not happen with valid input Err(e) => panic!("Error parsing token: {}", e), } } ``` ### Response #### Success Response - `PhpParser` instance (from `new`) - `Option>` (from `next_token`, containing the next token or `None` if end of input) #### Response Example ```rust // Example output from next_token(): // Some(PhpToken::Array { elements: 2 }) // Some(PhpToken::String(PhpBstr::new(b"foo"))) // Some(PhpToken::End) ``` ``` -------------------------------- ### PhpBstr Source: https://context7.com/nickbabcock/phpserz/llms.txt `PhpBstr<'a>` is a zero-copy byte string wrapper for borrowed `&'a [u8]` slices. It defers UTF-8 decoding to the caller via `to_str()` and provides `to_property()` to strip PHP visibility prefixes, exposing the logical property name and its access level. ```APIDOC ## `PhpBstr` — Zero-copy byte string `PhpBstr<'a>` wraps a borrowed `&'a [u8]` slice from the original input. UTF-8 decoding is deferred to the caller via `to_str()`, and `to_property()` strips PHP visibility prefixes to expose the logical property name and its access level. ```rust use phpserz::{ PhpBstr, PhpVisibility }; // Public property — no prefix let bstr = PhpBstr::new(b"username"); let prop = bstr.to_property(); assert_eq!(prop.to_str().unwrap(), "username"); assert_eq!(prop.visibility(), PhpVisibility::Public); // Private property — prefix: \0ClassName\0 let bstr = PhpBstr::new(b"\0MyClass\0secretField"); let prop = bstr.to_property(); assert_eq!(prop.to_str().unwrap(), "secretField"); assert_eq!(prop.visibility(), PhpVisibility::Private); // Protected property — prefix: \0*\0 let bstr = PhpBstr::new(b"\0*\0protectedVar"); let prop = bstr.to_property(); assert_eq!(prop.to_str().unwrap(), "protectedVar"); assert_eq!(prop.visibility(), PhpVisibility::Protected); // Raw bytes access (no UTF-8 check) assert_eq!(bstr.as_bytes(), b"\0*\0protectedVar"); ``` ``` -------------------------------- ### Deserialize PHP data to Rust structs with PhpDeserializer Source: https://context7.com/nickbabcock/phpserz/llms.txt Use `PhpDeserializer` to map PHP-serialized bytes directly onto Rust structs that derive `serde::Deserialize`. PHP object property visibility prefixes are automatically handled. ```rust use phpserz::PhpDeserializer; use serde::Deserialize; use std::collections::BTreeMap; #[derive(Debug, Deserialize, PartialEq)] struct Example { name: String, age: i32, #[serde(rename = "isActive")] is_active: bool, scores: BTreeMap, metadata: Metadata, } #[derive(Debug, Deserialize, PartialEq)] struct Metadata { id: i32, tags: BTreeMap, } // PHP: serialize(new Example(...)) let serialized = b"O:7:\"Example\":5:{s:4:\"name\";s:8:\"John Doe\";s:12:\"\0Example\0age\";i:42;s:11:\"\0*\0isActive\";b:1;s:6:\"scores\";a:3:{i:0;d:95.5;i:1;d:88.0;i:2;d:92.3;}s:8:\"metadata\";a:2:{s:2:\"id\";i:12345;s:4:\"tags\";a:3:{i:0;s:3:\"php\";i:1;s:4:\"rust\";i:2;s:13:\"serialization\";}}}"; let mut de = PhpDeserializer::new(serialized); let example = Example::deserialize(&mut de).unwrap(); assert_eq!(example.name, "John Doe"); assert_eq!(example.age, 42); assert!(example.is_active); assert_eq!(example.scores[&0], 95.5); assert_eq!(example.metadata.id, 12345); // Output: Example { name: "John Doe", age: 42, is_active: true, scores: {0: 95.5, 1: 88.0, 2: 92.3}, metadata: Metadata { id: 12345, tags: {0: "php", 1: "rust", 2: "serialization"} } } ``` -------------------------------- ### Deserialize PHP Null to Rust Option Fields Source: https://context7.com/nickbabcock/phpserz/llms.txt Illustrates how PHP null values (`N;`) are deserialized into Rust `Option` fields as `None`. Any other value will be deserialized as `Some(T)`. ```rust use phpserz::PhpDeserializer; use serde::Deserialize; #[derive(Debug, Deserialize, PartialEq)] struct UserProfile { username: String, email: Option, bio: Option, } let input = b"O:11:\"UserProfile\":3:{s:8:\"username\";s:8:\"john_doe\";s:5:\"email\";s:16:\"john@example.com\";s:3:\"bio\";N;}"; let result: UserProfile = Deserialize::deserialize(&mut PhpDeserializer::new(input)).unwrap(); assert_eq!(result.username, "john_doe"); assert_eq!(result.email, Some("john@example.com".to_string())); assert_eq!(result.bio, None); ``` -------------------------------- ### PhpToken Source: https://context7.com/nickbabcock/phpserz/llms.txt Each PHP serialized type maps to a `PhpToken` variant. Containers like `Array` and `Object` are initiated with an element or property count, followed by flat key-value token pairs, and terminated by an `End` token (`}`). ```APIDOC ## `PhpToken` — Token variants Every PHP serialized type maps to a `PhpToken` variant. Containers (`Array`, `Object`) are opened with an element/property count; their contents follow as flat key-value token pairs terminated by an `End` (`}`) token. ```rust use phpserz::{ PhpParser, PhpToken, PhpBstr, PhpReferenceKind }; // Null assert_eq!(PhpParser::new(b"N;").next_token().unwrap(), Some(PhpToken::Null)); // Boolean assert_eq!(PhpParser::new(b"b:1;").next_token().unwrap(), Some(PhpToken::Boolean(true))); // Integer (i64) assert_eq!(PhpParser::new(b"i:-9223372036854775808;").next_token().unwrap(), Some(PhpToken::Integer(i64::MIN))); // Float (f64) assert_eq!(PhpParser::new(b"d:1.7976931348623157E+308;").next_token().unwrap(), Some(PhpToken::Float(f64::MAX))); // String (zero-copy slice) assert_eq!(PhpParser::new(b"s:5:\"hello\";").next_token().unwrap(), Some(PhpToken::String(PhpBstr::new(b"hello")))); // Array: count followed by key-value pairs then End let mut p = PhpParser::new(b"a:1:{i:0;i:99;}"); assert_eq!(p.next_token().unwrap(), Some(PhpToken::Array { elements: 1 })); // Custom C object: raw payload bytes let mut p = PhpParser::new(b"C:5:\"MyObj\":6:{binary}"); assert_eq!(p.next_token().unwrap(), Some(PhpToken::CustomObject { class: PhpBstr::new(b"MyObj"), payload: PhpBstr::new(b"binary"), })); // Back-references assert_eq!( PhpParser::new(b"r:3;").next_token().unwrap(), Some(PhpToken::Reference { id: 3, kind: PhpReferenceKind::Repeated }) ); assert_eq!( PhpParser::new(b"R:5;").next_token().unwrap(), Some(PhpToken::Reference { id: 5, kind: PhpReferenceKind::Alias }) ); ``` ``` -------------------------------- ### PhpToken Variants for PHP Data Types Source: https://context7.com/nickbabcock/phpserz/llms.txt Each PHP serialized type maps to a `PhpToken` variant. Containers are followed by key-value pairs and terminated by `End`. ```rust use phpserz::{PhpParser, PhpToken, PhpBstr, PhpReferenceKind}; // Null assert_eq!(PhpParser::new(b"N;").next_token().unwrap(), Some(PhpToken::Null)); // Boolean assert_eq!(PhpParser::new(b"b:1;").next_token().unwrap(), Some(PhpToken::Boolean(true))); // Integer (i64) assert_eq!(PhpParser::new(b"i:-9223372036854775808;").next_token().unwrap(), Some(PhpToken::Integer(i64::MIN))); // Float (f64) assert_eq!(PhpParser::new(b"d:1.7976931348623157E+308;").next_token().unwrap(), Some(PhpToken::Float(f64::MAX))); // String (zero-copy slice) assert_eq!(PhpParser::new(b"s:5:\"hello\";").next_token().unwrap(), Some(PhpToken::String(PhpBstr::new(b"hello")))); // Array: count followed by key-value pairs then End let mut p = PhpParser::new(b"a:1:{i:0;i:99;}"); assert_eq!(p.next_token().unwrap(), Some(PhpToken::Array { elements: 1 })); // Custom C object: raw payload bytes let mut p = PhpParser::new(b"C:5:\"MyObj\":6:{binary}"); assert_eq!(p.next_token().unwrap(), Some(PhpToken::CustomObject { class: PhpBstr::new(b"MyObj"), payload: PhpBstr::new(b"binary"), })); // Back-references assert_eq!( PhpParser::new(b"r:3;").next_token().unwrap(), Some(PhpToken::Reference { id: 3, kind: PhpReferenceKind::Repeated }) ); assert_eq!( PhpParser::new(b"R:5;").next_token().unwrap(), Some(PhpToken::Reference { id: 5, kind: PhpReferenceKind::Alias }) ); ``` -------------------------------- ### PhpParser::peek_token Source: https://context7.com/nickbabcock/phpserz/llms.txt `peek_token` provides a non-consuming lookahead, returning the `PhpTokenKind` of the next token without advancing the parser's cursor. This is helpful for checking for the `End` token (`}`) to determine if a container is exhausted before reading. ```APIDOC ## `PhpParser::peek_token` — Non-consuming lookahead `peek_token` returns the `PhpTokenKind` of the next token without advancing the cursor. Calling it multiple times returns the same kind. This is useful for detecting `}` (the `End` token) to know when a container is exhausted before committing to a read. ```rust use phpserz::{ PhpParser, PhpToken, PhpTokenKind }; let mut parser = PhpParser::new(b"i:42;s:5:\"hello\";"); // Peek without consuming assert_eq!(parser.peek_token().unwrap(), Some(PhpTokenKind::Integer)); assert_eq!(parser.position(), 0); // cursor unchanged // Now read assert_eq!(parser.next_token().unwrap(), Some(PhpToken::Integer(42))); assert_eq!(parser.position(), 5); // Peek again assert_eq!(parser.peek_token().unwrap(), Some(PhpTokenKind::String)); assert_eq!(parser.position(), 5); // still unchanged ``` ``` -------------------------------- ### Peek Token for Non-Consuming Lookahead Source: https://context7.com/nickbabcock/phpserz/llms.txt Use `peek_token` to inspect the next token's kind without advancing the parser's position. Useful for checking for end-of-container markers. ```rust use phpserz::{PhpParser, PhpToken, PhpTokenKind}; let mut parser = PhpParser::new(b"i:42;s:5:\"hello\";"); // Peek without consuming assert_eq!(parser.peek_token().unwrap(), Some(PhpTokenKind::Integer)); assert_eq!(parser.position(), 0); // cursor unchanged // Now read assert_eq!(parser.next_token().unwrap(), Some(PhpToken::Integer(42))); assert_eq!(parser.position(), 5); // Peek again assert_eq!(parser.peek_token().unwrap(), Some(PhpTokenKind::String)); assert_eq!(parser.position(), 5); // still unchanged ``` -------------------------------- ### PhpParser::read_token Source: https://context7.com/nickbabcock/phpserz/llms.txt `read_token` is similar to `next_token` but specifically returns `Err(ErrorKind::Eof)` when the input is exhausted. This is useful when more tokens are expected and an early end signifies an error. ```APIDOC ## `PhpParser::read_token` — Infallible-end token read `read_token` is like `next_token` but returns `Err(ErrorKind::Eof)` instead of `Ok(None)` when the input is exhausted, making it convenient when more tokens are expected and an early end is always an error. ```rust use phpserz::{ PhpParser, PhpToken, PhpBstr, PhpVisibility }; let input = b"O:3:\"Foo\":1:{s:3:\"bar\";i:99;}"; let mut parser = PhpParser::new(input); // Object header let PhpToken::Object { class, properties } = parser.read_token().unwrap() else { panic!() }; assert_eq!(class, PhpBstr::new(b"Foo")); assert_eq!(properties, 1); // Property key — a raw string token; decode visibility separately let PhpToken::String(key) = parser.read_token().unwrap() else { panic!() }; let prop = key.to_property(); assert_eq!(prop.to_str().unwrap(), "bar"); assert_eq!(prop.visibility(), PhpVisibility::Public); // Property value assert_eq!(parser.read_token().unwrap(), PhpToken::End.into()); // just the closing brace // actual value first: ``` ``` -------------------------------- ### Read Token with Error Handling for EOF Source: https://context7.com/nickbabcock/phpserz/llms.txt Use `read_token` when an early end of input is an error. It returns `Err(ErrorKind::Eof)` instead of `Ok(None)`. ```rust use phpserz::{PhpParser, PhpToken, PhpBstr, PhpVisibility}; let input = b"O:3:\"Foo\":1:{s:3:\"bar\";i:99;}"; let mut parser = PhpParser::new(input); // Object header let PhpToken::Object { class, properties } = parser.read_token().unwrap() else { panic!() }; assert_eq!(class, PhpBstr::new(b"Foo")); assert_eq!(properties, 1); // Property key — a raw string token; decode visibility separately let PhpToken::String(key) = parser.read_token().unwrap() else { panic!() }; let prop = key.to_property(); assert_eq!(prop.to_str().unwrap(), "bar"); assert_eq!(prop.visibility(), PhpVisibility::Public); // Property value assert_eq!(parser.read_token().unwrap(), PhpToken::End.into()); // just the closing brace // actual value first: ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.