//! Bounded `LLSD`/`OSD` support corresponding to `LibreMetaverse.StructuredData`. //! //! `XML`, `JSON`, binary, and notation codecs share checked depth, node, and byte //! limits. Choose this crate for standalone structured-data work without //! constructing a grid client or enabling a native codec. extern crate self as libremetaverse_structured_data; mod binary; mod dispatch; mod generated; #[cfg(test)] mod hardening; mod json_codec; mod model; mod notation; mod protobuf; mod xml_codec; pub mod xml { use std::sync::{Arc, Mutex}; /// Project-owned XML element boundary; external XML APIs are not copied. pub struct Element; /// Native XML reader boundary; external XML APIs are not copied. #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct Reader(pub String); /// Native XML writer boundary; external XML APIs are not copied. #[derive(Clone, Debug, Default)] pub struct Writer(pub Arc>); impl Writer { #[must_use] pub fn contents(&self) -> String { self.0 .lock() .unwrap_or_else(std::sync::PoisonError::into_inner) .clone() } pub(crate) fn append(&self, value: &str) -> Result<(), crate::Error> { let mut output = self.0.lock().map_err(|_| crate::Error::InvalidOperation)?; let length = output .len() .checked_add(value.len()) .ok_or(crate::Error::Argument)?; if length > crate::OSD::DEFAULT_MAX_BINARY_BYTES { return Err(crate::Error::Argument); } output.push_str(value); Ok(()) } } } pub use generated::*; pub use libremetaverse_types as types; pub use libremetaverse_types::Error; /// Decodes one bounded binary LLSD value and returns the number of consumed /// bytes, allowing native container formats to locate payloads appended after /// an LLSD header without duplicating the codec. /// /// # Errors /// /// Returns a positioned parse error when the prefix is malformed, truncated, /// or exceeds the shared LLSD depth, node, input, or allocation bounds. pub fn deserialize_llsd_binary_prefix(data: &[u8]) -> Result<(OSD, usize), Error> { binary::deserialize_prefix(data) }