oxedyne/fe2o3/fe2o3_jdat/src/lib.rs
4.5 KiB, 15 runs
created by r1870400018:473, which is this file's identity for as long as the history lasts, whatever it is later renamed to
download · who wrote it · its history
| 1 | //! A library implementing Jason's Data And Type (JDAT) scheme, a typed superset of JSON providing |
| 2 | //! both text and binary serialisation. |
| 3 | //! |
| 4 | //! The two encodings carry the same information and each has its own module. The text form, in |
| 5 | //! [`string`], is the one an author reads and writes, as in `(u8|42)`. The binary form, in |
| 6 | //! [`bdat`], is BDAT, which stands to JDAT as BSON does to JSON, and is what travels on the wire |
| 7 | //! and rests on disk. |
| 8 | //! |
| 9 | //! JDAT extends JSON by adding: |
| 10 | //! - Optional type annotations with a rich set of built-in types |
| 11 | //! - Support for arbitrary-precision numbers and compact binary encoding |
| 12 | //! - User-defined type extensions through a flexible system |
| 13 | //! - Comments and trailing commas for improved readability |
| 14 | //! - Any type as map keys, not just strings |
| 15 | //! |
| 16 | //! The library provides: |
| 17 | //! - Complete text and binary serialisation/deserialisation |
| 18 | //! - Derive macros for automatic implementation of conversion traits |
| 19 | //! - Full compatibility with existing JSON data |
| 20 | //! - Optimised binary encoding for network transfers |
| 21 | //! - Support for streaming and incremental parsing |
| 22 | //! |
| 23 | //! # Examples |
| 24 | //! |
| 25 | //! The following example demonstrates core concepts including daticles (type-annotated values like |
| 26 | //! `(u8|42)`), kindicles (type annotations like `u8|`), and the different text encodings available: |
| 27 | //! |
| 28 | //! ```rust |
| 29 | //! use oxedyne_fe2o3_jdat::{ |
| 30 | //! prelude::*, |
| 31 | //! string::{ |
| 32 | //! dec::DecoderConfig, |
| 33 | //! enc::EncoderConfig, |
| 34 | //! }, |
| 35 | //! }; |
| 36 | //! use oxedyne_fe2o3_core::prelude::*; |
| 37 | //! use std::collections::BTreeMap; |
| 38 | //! |
| 39 | //! fn main() -> Outcome<()> { |
| 40 | //! // Create a sample data structure |
| 41 | //! let data = mapdat!{ |
| 42 | //! "name" => "Alice", |
| 43 | //! "age" => 21u8, |
| 44 | //! "scores" => listdat![95u8, 87u8, 92u8], |
| 45 | //! dat!(42u8) => "Answer", // Non-string key, not possible in JSON |
| 46 | //! }; |
| 47 | //! |
| 48 | //! // Standard JSON format (no type annotations) |
| 49 | //! let json_cfg = EncoderConfig::<(), ()>::json(None); |
| 50 | //! println!("JSON format:"); |
| 51 | //! println!("{}", res!(data.encode_string_with_config(&json_cfg))); |
| 52 | //! // Output: |
| 53 | //! // { |
| 54 | //! // "name": "Alice", |
| 55 | //! // "age": 21, |
| 56 | //! // "scores": [95, 87, 92], |
| 57 | //! // "42": "Answer" |
| 58 | //! // } |
| 59 | //! |
| 60 | //! // Display format (most common types inferred) |
| 61 | //! println!("\nDisplay format (KindScope::Most):"); |
| 62 | //! println!("{}", data); |
| 63 | //! // Output: |
| 64 | //! // { |
| 65 | //! // "name": "Alice", |
| 66 | //! // "age": (u8|21), |
| 67 | //! // "scores": [95, 87, 92], |
| 68 | //! // (u8|42): "Answer" |
| 69 | //! // } |
| 70 | //! |
| 71 | //! // Debug format (all types shown) |
| 72 | //! println!("\nDebug format (KindScope::Everything):"); |
| 73 | //! println!("{:?}", data); |
| 74 | //! // Output: |
| 75 | //! // (map|{ |
| 76 | //! // (str|"name"): (str|"Alice"), |
| 77 | //! // (str|"age"): (u8|21), |
| 78 | //! // (str|"scores"): (list|[(u8|95), (u8|87), (u8|92)]), |
| 79 | //! // (u8|42): (str|"Answer") |
| 80 | //! // }) |
| 81 | //! |
| 82 | //! // Demonstrate manual daticle creation and binary conversion |
| 83 | //! let d1 = Dat::U8(42); // Manual construction |
| 84 | //! let d2 = dat!(42); // Macro construction (sized to u8) |
| 85 | //! let k = d1.kind(); // Get the kind (Kind::U8) |
| 86 | //! |
| 87 | //! // Convert to bytes |
| 88 | //! let mut buf = Vec::new(); |
| 89 | //! buf = res!(d1.to_bytes(buf)); |
| 90 | //! |
| 91 | //! // Parse a daticle from text |
| 92 | //! let d3 = res!(Dat::decode_string("(i8|-42)")); |
| 93 | //! |
| 94 | //! // Parse a recursive daticle |
| 95 | //! let d4 = res!(Dat::decode_string("(map|{ \"age\": (u8|21)})")); |
| 96 | //! |
| 97 | //! Ok(()) |
| 98 | //! } |
| 99 | //! ``` |
| 100 | //! |
| 101 | //! The key innovation in Jdat is the daticle format, which consists of: |
| 102 | //! - An optional kindicle (type annotation) in parentheses, e.g. `(u8|` |
| 103 | //! - A value that matches the type, e.g. `42)` |
| 104 | //! - Together forming `(u8|42)` |
| 105 | //! |
| 106 | //! Types can be inferred where unambiguous, and kindicles can be omitted for common types like |
| 107 | //! strings and maps in most contexts. The level of type annotation is controlled by the |
| 108 | //! `KindScope` setting, allowing for formats ranging from JSON-compatible to fully typed. |
| 109 | //! |
| 110 | #![forbid(unsafe_code)] |
| 111 | |
| 112 | #[macro_use] |
| 113 | pub mod macros; |
| 114 | |
| 115 | pub mod bdat; |
| 116 | pub mod cfg; |
| 117 | pub mod chunk; |
| 118 | pub mod constant; |
| 119 | pub mod conv; |
| 120 | pub mod daticle; |
| 121 | pub mod file; |
| 122 | pub mod id; |
| 123 | pub mod int; |
| 124 | pub mod kind; |
| 125 | pub mod map; |
| 126 | pub mod note; |
| 127 | pub mod prelude; |
| 128 | pub mod string; |
| 129 | pub mod usr; |
| 130 | pub mod version; |
| 131 | |
| 132 | use oxedyne_fe2o3_core::prelude::*; |
| 133 | |
| 134 | pub use oxedyne_fe2o3_core::conv::BestFrom; |
| 135 | |
| 136 | pub use dat_map::{ |
| 137 | FromDatMap, |
| 138 | ToDatMap, |
| 139 | }; |
| 140 | |
| 141 | pub use crate::{ |
| 142 | daticle::Dat, |
| 143 | kind::Kind, |
| 144 | }; |