Sign in

    moon-ron

    A strict RON parser, serializer, formatter, and typed codec for MoonBit.

    ron
    parser
    serialization
    configuration
    Download zip
    Author
    Version
    0.2.0
    License
    Apache-2.0
    Last updated
    4 days ago
    Downloads
    7

    Dependencies

    #L76148/moon-ron

    A strict RON parser, serializer, formatter, and typed codec for MoonBit.

    The current implementation provides six independently verified capabilities: parsing a RON document into a dynamically typed RonValue, serializing that value back to compact canonical RON text, formatting structured values as readable multiline RON, converting between RON values and typed MoonBit values through FromRon and ToRon, applying document extension attributes, and checking or formatting files through a CLI.

    The library core has no runtime dependencies. The CLI uses the official moonbitlang/x/fs package for file access.

    The mon package adds MON, a data notation whose literals are MoonBit's own literals, so a data document reads like the code around it:

    Config { name: "api", ports: [8080, 8081], limits: { "cpu": 4, "memory": 1024U }, window: 1..=10, }

    cmd/mon checks a document, and docs/MON.md records every accepted spelling together with the forms the MoonBit compiler rejects.

    #Install

    moon add L76148/moon-ron@0.2.0

    #Why RON

    MoonBit already has established packages for JSON, TOML, YAML, KDL, and HCL. RON occupies a distinct point in that space: it keeps Rust-style structs, tuple variants, enums, options, bytes, and comments while remaining readable as configuration data. An independent MoonBit implementation makes it useful for test fixtures, game data, and exchange files generated by Rust services.

    #Supported syntax

    • Unit, booleans, characters, strings, byte strings, byte characters
    • Signed integers, unsigned integers, floats, infinities, and NaN
    • Sequences, tuples, maps, named structs, tuple structs, and enum variants
    • Closed, open-ended, and inclusive ranges
    • Some, None, line comments, nested block comments, and raw strings
    • Bounded nesting depth and source-positioned errors

    #Use

    let value = @ron.parse( "Point(x: 1, y: 2, tags: [\"parser\", \"ron\"])", ) let source = @ron.to_string(value) let readable = @ron.to_string_pretty(value, indent=2)

    Typed values implement two traits:

    impl @ron.ToRon for Point with fn to_ron(self, options) { ... } impl @ron.FromRon for Point with fn from_ron(value, path, options) { ... } let source = @ron.encode(point) let point : Point = @ron.decode(source)

    The root package exports:

    • parse(source, max_nesting_depth?)
    • to_string(value)
    • to_string_pretty(value, indent?)
    • decode[T](source, max_nesting_depth?)
    • decode_with_options[T](source, options?)
    • encode[T](value)
    • encode_with_options[T](value, options?)
    • FromRon and ToRon
    • valid(source)
    • parse_document(source, options?)
    • RonValue, RonNumber, RonPosition, RonError, RonPath, and RonDecodeError
    • RonExtensions, RonOptions, and RonDocument
    • render_error(source, error) and render_decode_error(source, error)

    Run the bundled example:

    moon run cmd/main moon run cmd/typed moon run cmd/extensions

    Run the CLI:

    moon run cmd/ron -- check corpus/basic.ron moon run cmd/ron -- format corpus/basic.ron moon run cmd/ron -- compact corpus/kitchen_sink.ron

    Run the quality gates:

    moon check --deny-warn moon test --deny-warn moon fmt --check

    #Design notes

    The parser keeps syntax and semantic conversion separate. RonValue is a lossless-enough generic tree for parsing, inspection, and future conversion. The serializer emits compact deterministic syntax and keeps numeric type boundaries across a parse/serialize round trip. Typed decoding will be added as a separate trait layer instead of complicating either operation.

    The project is licensed under Apache-2.0. The RON language and the Rust ron crate are used as a compatibility reference; no upstream source code is copied in this increment. See THIRD_PARTY_NOTICES.md.

    FromRon

    pub(open) trait FromRon {
    fn from_ron(RonValue, RonPath, RonOptions) -> Self raise RonDecodeError
    }

    Trait for values that can be decoded from a RonValue.
    impl FromRon for Unit
    impl FromRon for Bool
    impl FromRon for Byte
    impl FromRon for Char
    impl FromRon for Int
    impl FromRon for Int16
    impl FromRon for Int64
    impl FromRon for UInt
    impl FromRon for UInt16
    impl FromRon for UInt64
    impl FromRon for Float
    impl FromRon for Double
    impl FromRon for String
    impl FromRon for Option[T]
    impl FromRon for Result[Ok, Err]
    impl FromRon for FixedArray[T]
    impl FromRon for Bytes
    impl FromRon for Array[T]
    impl FromRon for Map[String, V]
    impl FromRon for Tuple2[A, B]
    impl FromRon for Tuple3[A, B, C]
    impl FromRon for Tuple4[A, B, C, D]
    impl FromRon for Tuple5[A, B, C, D, E]
    impl FromRon for Tuple6[A, B, C, D, E, F]
    impl FromRon for Tuple7[A, B, C, D, E, F, G]
    impl FromRon for Tuple8[A, B, C, D, E, F, G, H]

    ToRon

    pub(open) trait ToRon {
    fn to_ron(Self, RonOptions) -> RonValue
    }

    Trait for values that can be encoded as a RonValue.
    impl ToRon for Unit
    impl ToRon for Bool
    impl ToRon for Byte
    impl ToRon for Char
    impl ToRon for Int
    impl ToRon for Int16
    impl ToRon for Int64
    impl ToRon for UInt
    impl ToRon for UInt16
    impl ToRon for UInt64
    impl ToRon for Float
    impl ToRon for Double
    impl ToRon for String
    impl ToRon for Option[T]
    impl ToRon for Result[Ok, Err]
    impl ToRon for FixedArray[T]
    impl ToRon for Bytes
    impl ToRon for Array[T]
    impl ToRon for ArrayView[T]
    impl ToRon for Map[String, V]
    impl ToRon for Tuple2[A, B]
    impl ToRon for Tuple3[A, B, C]
    impl ToRon for Tuple4[A, B, C, D]
    impl ToRon for Tuple5[A, B, C, D, E]
    impl ToRon for Tuple6[A, B, C, D, E, F]
    impl ToRon for Tuple7[A, B, C, D, E, F, G]
    impl ToRon for Tuple8[A, B, C, D, E, F, G, H]

    RonDecodeError

    pub(all) suberror RonDecodeError {
    Syntax(RonError)
    TypeMismatch(RonPath, String, String)
    MissingField(RonPath, String)
    UnexpectedTupleLength(RonPath, Int, Int)
    UnknownVariant(RonPath, String)
    InvalidValue(RonPath, String)
    } derive(Eq,
    Debug
    )

    Errors raised by typed RON decoding.

    RonDecodeError::equal

    RonDecodeError::not_equal

    fn RonDecodeError::not_equal(x : RonDecodeError, y : RonDecodeError) -> Bool

    RonError

    pub(all) suberror RonError {
    UnexpectedChar(RonPosition, Char)
    UnexpectedEof(RonPosition)
    InvalidEscape(RonPosition)
    InvalidNumber(RonPosition, String)
    InvalidValue(RonPosition, String)
    UnknownExtension(RonPosition, String)
    UnknownAttribute(RonPosition, String)
    InvalidAttribute(RonPosition, String)
    DepthLimitExceeded(Int)
    } derive(Eq,
    Debug
    )

    Errors raised while parsing RON source.

    RonError::equal

    fn RonError::equal(RonError, RonError) -> Bool

    RonError::not_equal

    fn RonError::not_equal(x : RonError, y : RonError) -> Bool

    RonError::to_repr

    RonDocument

    pub(all) struct RonDocument {
    value : RonValue
    extensions : RonExtensions
    } derive(Eq,
    Debug
    )

    A parsed RON value together with the extensions enabled by its attributes.

    RonDocument::equal

    fn RonDocument::equal(RonDocument, RonDocument) -> Bool

    RonDocument::not_equal

    fn RonDocument::not_equal(x : RonDocument, y : RonDocument) -> Bool

    RonExtensions

    pub(all) struct RonExtensions {
    unwrap_newtypes : Bool
    implicit_some : Bool
    unwrap_variant_newtypes : Bool
    explicit_struct_names : Bool
    } derive(Eq,
    Debug
    )

    Optional RON behavior enabled by a document attribute or caller options.

    RonExtensions::add

    RonExtensions::empty

    RonExtensions::equal

    RonExtensions::from_name

    fn RonExtensions::from_name(name : String) -> RonExtensions?

    RonExtensions::is_empty

    fn RonExtensions::is_empty(self : RonExtensions) -> Bool

    RonExtensions::not_equal

    fn RonExtensions::not_equal(x : RonExtensions, y : RonExtensions) -> Bool

    RonExtensions::to_attribute

    fn RonExtensions::to_attribute(self : RonExtensions) -> String

    RonNumber

    pub(all) enum RonNumber {
    Signed(Int64)
    Unsigned(UInt64)
    Float(Double)
    Infinity
    NegativeInfinity
    NaN
    } derive(Eq,
    Debug
    )

    A numeric value in a RON document.

    RonNumber::equal

    fn RonNumber::equal(RonNumber, RonNumber) -> Bool

    RonNumber::not_equal

    fn RonNumber::not_equal(x : RonNumber, y : RonNumber) -> Bool

    RonOptions

    pub(all) struct RonOptions {
    extensions : RonExtensions
    max_nesting_depth : Int
    } derive(Eq,
    Debug
    )

    Parsing options and document-level extension defaults.

    RonOptions::default

    fn RonOptions::default() -> RonOptions

    RonOptions::equal

    fn RonOptions::equal(RonOptions, RonOptions) -> Bool

    RonOptions::not_equal

    fn RonOptions::not_equal(x : RonOptions, y : RonOptions) -> Bool

    RonOptions::with_extension

    fn RonOptions::with_extension(self : RonOptions, extension : RonExtensions) -> RonOptions

    RonOptions::with_extensions

    fn RonOptions::with_extensions(self : RonOptions, extensions : RonExtensions) -> RonOptions

    RonOptions::with_max_nesting_depth

    fn RonOptions::with_max_nesting_depth(self : RonOptions, max_nesting_depth : Int) -> RonOptions

    RonPath

    pub(all) enum RonPath {
    Root
    Key(String, RonPath)
    Index(Int, RonPath)
    Variant(String, RonPath)
    } derive(Eq,
    Debug
    )

    A path from a decoded root value to the value that caused an error.

    RonPath::add_index

    fn RonPath::add_index(self : RonPath, index : Int) -> RonPath

    RonPath::add_key

    fn RonPath::add_key(self : RonPath, key : String) -> RonPath

    RonPath::add_variant

    fn RonPath::add_variant(self : RonPath, variant : String) -> RonPath

    RonPath::equal

    fn RonPath::equal(RonPath, RonPath) -> Bool

    RonPath::not_equal

    fn RonPath::not_equal(x : RonPath, y : RonPath) -> Bool

    RonPath::root

    fn RonPath::root() -> RonPath

    RonPath::to_repr

    RonPath::to_string

    fn RonPath::to_string(self : RonPath) -> String

    RonPosition

    pub(all) struct RonPosition {
    index : Int
    line : Int
    column : Int
    } derive(Eq,
    Debug
    )

    A source position measured in Unicode scalar values.

    RonPosition::equal

    fn RonPosition::equal(RonPosition, RonPosition) -> Bool

    RonPosition::not_equal

    fn RonPosition::not_equal(x : RonPosition, y : RonPosition) -> Bool

    RonRange

    pub(all) struct RonRange {
    start : RonValue?
    end : RonValue?
    inclusive : Bool
    } derive(Eq,
    Debug
    )

    A possibly open-ended RON range.
    impl FromRon for RonRange
    impl ToRon for RonRange

    RonRange::equal

    fn RonRange::equal(RonRange, RonRange) -> Bool

    RonRange::from_ron

    fn RonRange::from_ron(value : RonValue, path : RonPath, _ : RonOptions) -> RonRange raise RonDecodeError

    RonRange::new

    fn RonRange::new(start? : RonValue, end? : RonValue, inclusive? : Bool) -> RonRange

    RonRange::not_equal

    fn RonRange::not_equal(x : RonRange, y : RonRange) -> Bool

    RonRange::to_repr

    RonRange::to_ron

    fn RonRange::to_ron(self : RonRange, _ : RonOptions) -> RonValue

    RonValue

    pub(all) enum RonValue {
    Unit
    Bool(Bool)
    Number(RonNumber)
    Char(Char)
    String(String)
    Bytes(Bytes)
    Byte(Byte)
    Option(RonValue?)
    Sequence(Array[RonValue])
    Tuple(Array[RonValue])
    Map(Array[(RonValue, RonValue)])
    Struct(String, Array[(String, RonValue)])
    TupleStruct(String, Array[RonValue])
    Enum(String, String, Array[(String, RonValue)])
    EnumTuple(String, String, Array[RonValue])
    Range(RonRange)
    Identifier(String)
    } derive(Eq,
    Debug
    )

    A dynamically typed RON value.
    impl FromRon for RonValue
    impl ToRon for RonValue

    RonValue::equal

    fn RonValue::equal(RonValue, RonValue) -> Bool

    RonValue::from_ron

    fn RonValue::from_ron(value : RonValue, _ : RonPath, _ : RonOptions) -> RonValue raise RonDecodeError

    RonValue::not_equal

    fn RonValue::not_equal(x : RonValue, y : RonValue) -> Bool

    RonValue::to_repr

    RonValue::to_ron

    fn RonValue::to_ron(self : RonValue, _ : RonOptions) -> RonValue

    decode

    fn[T : FromRon] decode(source : StringView, max_nesting_depth? : Int) -> T raise RonDecodeError

    Decode one RON document into a typed value.

    decode_with_options

    fn[T : FromRon] decode_with_options(source : StringView, options? : RonOptions) -> T raise RonDecodeError

    Decode one RON document using explicit extension and depth options.

    encode

    fn[T : ToRon] encode(value : T) -> String

    Encode a typed value as canonical RON text.

    encode_with_options

    fn[T : ToRon] encode_with_options(value : T, options? : RonOptions) -> String

    Encode a typed value with an optional RON extension header.

    field

    fn[T : FromRon] field(fields : Array[(String, RonValue)], name : String, path : RonPath, options : RonOptions) -> T raise RonDecodeError

    field_value

    fn field_value(fields : Array[(String, RonValue)], name : String, path : RonPath) -> RonValue raise RonDecodeError

    from_value

    fn[T : FromRon] from_value(value : RonValue) -> T raise RonDecodeError

    Decode an already parsed RON value.

    from_value_with_options

    fn[T : FromRon] from_value_with_options(value : RonValue, options : RonOptions) -> T raise RonDecodeError

    Decode an already parsed RON value using explicit options.

    newtype

    fn[T : FromRon] newtype(value : RonValue, path : RonPath, options : RonOptions) -> T raise RonDecodeError

    Decode a newtype payload, honoring unwrap_newtypes.

    parse

    fn parse(source : StringView, max_nesting_depth? : Int) -> RonValue raise RonError

    Parse one RON document into a dynamically typed value.

    The parser accepts comments, all RON scalar forms, sequences, tuples, maps, named structs, tuple structs, and enum variants. The optional max_nesting_depth applies to containers and typed payloads.

    parse_document

    fn parse_document(source : StringView, options? : RonOptions) -> RonDocument raise RonError

    Parse one RON document and return its value and active extensions.

    positional

    fn[T : FromRon] positional(values : Array[RonValue], index : Int, path : RonPath, options : RonOptions) -> T raise RonDecodeError

    render_decode_error

    fn render_decode_error(source : StringView, error : RonDecodeError) -> String

    Render a typed decoding error. Syntax errors include a source caret.

    render_error

    fn render_error(source : StringView, error : RonError) -> String

    Render a parser error with its source line and a caret.

    require_struct_name

    fn require_struct_name(value : RonValue, expected : String, path : RonPath, options : RonOptions) -> Unit raise RonDecodeError

    Require a named struct when explicit_struct_names is enabled.

    struct_fields

    fn struct_fields(value : RonValue, path : RonPath) -> Array[(String, RonValue)] raise RonDecodeError

    to_string

    fn to_string(value : RonValue) -> String

    Serialize a RON value using the parser's canonical compact syntax.

    The result is valid input for parse whenever names and identifiers in the value satisfy the RON identifier grammar. Floating-point values that would otherwise look like integers keep a .0 suffix.

    to_string_pretty

    fn to_string_pretty(value : RonValue, indent? : Int) -> String

    Serialize a RON value using deterministic multiline formatting.

    indent is the number of spaces added for each nesting level. Negative values are treated as zero. Empty containers remain on one line.

    to_value

    fn[T : ToRon] to_value(value : T) -> RonValue

    Encode a typed value as a RonValue.

    to_value_with_options

    fn[T : ToRon] to_value_with_options(value : T, options : RonOptions) -> RonValue

    Encode a typed value as a RonValue using explicit options.

    tuple_fields

    fn tuple_fields(value : RonValue, path : RonPath) -> Array[RonValue] raise RonDecodeError

    valid

    fn valid(source : StringView) -> Bool

    Parse one RON document and return false when parsing fails.

    value_type_name

    fn value_type_name(value : RonValue) -> String

    Return the display name of a dynamic RON value.

    variant_newtype

    fn[T : FromRon] variant_newtype(value : RonValue, variant : String, path : RonPath, options : RonOptions) -> T raise RonDecodeError

    Decode an enum newtype payload, honoring unwrap_variant_newtypes.