Skip to main content

Crate one_brackets

Crate one_brackets 

Source
Expand description

Reader and writer for the 1C:Enterprise bracket format: {1,"text",{nested,list}}.

Input is anything implementing std::io::Read; the result is a Node tree. The API is built on the standard conversion traits:

use one_brackets::Node;

let node: Node = "\u{feff}{2,c2f34349-b1e0-4060-8abf-3c59f38ac69f,\"ок\"}".parse()?;
assert_eq!(node.try_get(0)?.try_i64()?, 2);
assert!(node[1].as_guid().is_some());
assert_eq!(node[2].as_quoted(), Some("ок"));

// Writing uses the platform layout.
let text: String = (&node).into();
assert_eq!(text, "{2,c2f34349-b1e0-4060-8abf-3c59f38ac69f,\"ок\"}");

// Any `Read` source: file, socket, decompressed stream.
let node = Node::from_reader(std::io::Cursor::new(b"{1,{}}"))?;
assert_eq!(node, Node::list([Node::from(1), Node::list([])]));

// Edit in place and write back: untouched parts keep their text.
let mut node: Node = "{1,\"old\",{2}}".parse()?;
*node.try_get_path_mut(&[2, 0])? = Node::from(3);
node[1] = Node::string("new");
assert_eq!(node.to_string(), "{1,\"new\",\r\n{3}\r\n}");

// Errors carry a position.
let err = Node::try_from("{1,\n{2").unwrap_err();
assert_eq!(
    err.to_string(),
    "unexpected end of input at line 2, column 3: list opened at line 2, column 1 is not closed",
);

Map your own types with impl TryFrom<&Node> using the try_* accessors. They return an AccessError that names the expected type and points at the node:

use one_brackets::{AccessError, Node};

#[derive(Debug)]
struct FormatVersion { major: u32, build: u64 }

impl TryFrom<&Node> for FormatVersion {
    type Error = AccessError;

    fn try_from(node: &Node) -> Result<Self, AccessError> {
        Ok(FormatVersion {
            major: node.try_get_path(&[0, 0])?.try_parse()?,
            build: node.try_get_path(&[0, 2, 0])?.try_parse()?,
        })
    }
}

let node: Node = "{\r\n{216,0,\r\n{x,0}\r\n}\r\n}".parse().unwrap();
let err = FormatVersion::try_from(&node).unwrap_err();
assert_eq!(
    err.to_string(),
    "expected u64, found value `x` at line 3, column 2: invalid digit found in string",
);

Parsing problems are reported as ParseError, structure problems as AccessError; Error wraps both, so ? works for either in one function.

With the serde feature user types map to lists by field order: see from_node, to_node, Rest, Counted and atom.

§Performance

Every string and value is a separate String and every list a Vec, so most of the parsing time of large files (event logs, big forms) goes to the memory allocator. The library does not pick an allocator; the application can switch to mimalloc, which works on Windows, Linux and macOS. In the crate’s measurements it made parsing 1.5–2.7 times faster on Windows, whose system allocator is the slowest, and 1.2–1.5 times faster on Linux (glibc):

[dependencies]
mimalloc = "0.1"
ⓘ
#[global_allocator]
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;

For large inputs prefer Values over parsing one huge list: it keeps only the current record in memory. cargo bench measures reading and writing speed.

Modules§

atomserde
Field helper for #[serde(with = "one_brackets::atom")].

Structs§

AccessError
The text is valid, but a node does not have the expected shape.
Countedserde
A counted list {count,item1,item2,...}, the common 1C shape.
Node
A node of a bracket file: a Value plus the position it was parsed from.
Position
Position in the input.
Restserde
Remaining items of a list after the preceding fields, kept as is.
SerializeErrorserde
A value cannot be represented in the bracket format.
Values
Comma-separated top-level values read one at a time, e.g. records of an event log .lgp.

Enums§

AccessErrorKind
What exactly went wrong in an AccessError.
Error
Either kind of error, for code that parses and maps in one function.
ParseError
The input could not be read or is not valid bracket text.
Value
Content of a Node.

Functions§

from_nodeserde
Deserializes a user type from a node; &str fields can borrow from the node.
from_readerserde
Reads bracket text from any Read and deserializes a user type from it.
from_strserde
Parses bracket text and deserializes a user type from it.
to_nodeserde
Serializes a user type into a node tree.
to_stringserde
Serializes a user type into bracket text in the platform layout.

Type Aliases§

Result