Language values and documents

Your application keeps its own structs, records, dataclasses and maps. The typed layer copies them into native documents and copies documents back into them. The native document API stays available beside it for work that needs native fidelity or no conversion.

Choose an interface

UseWhen you want to
Language values (encode, decode, typed rows)Write and read ordinary application data in the types of your language.
DocumentsReuse a value in several calls without converting it again, keep duplicate keys and member order exactly, or batch native work.
Parse and serializeRead or write text or bytes at a file or network boundary. See Formats and conversion.
Builders and node readsConstruct or walk documents node by node. See Documents and Building documents.

Example

The example stores three people from language values, runs a query written in the selected format, and decodes each row into a value of the language. The captured result is the decoded rows, encoded again for display.

Store Rust structs and read typed rows

query_text holds this document:

json134 B
{
  "find": [
    "?name"
  ],
  "where": [
    [
      "?e",
      "name",
      "?name"
    ]
  ],
  "orderBy": [
    "?name"
  ]
}
rust960 B
#[derive(serde::Serialize)]
struct Person {
    name: &'static str,
    role: &'static str,
    age: i64,
}
#[derive(serde::Serialize, serde::Deserialize)]
struct Name {
    name: String,
}
let database = stardust::open(database_path, &stardust::Options::default())?;
let people = std::collections::BTreeMap::from([
    ("#_ada", Person { name: "Ada", role: "engineer", age: 36 }),
    ("#_bob", Person { name: "Bob", role: "engineer", age: 41 }),
    ("#_cy", Person { name: "Cy", role: "designer", age: 29 }),
]);
stardust::merge_patch_value(&database, &people, None)?;
let definition = stardust::parse(query_text, Format::JSON)?;
let query = database.query(&definition)?;
let mut rows = query.run(None, &RunOptions::default(), None)?;
let mut values = rows.values::<Name>();
let mut names = Vec::new();
while let Some(row) = values.next() {
    names.push(row?);
}
drop(values);
let result = stardust::encode(&names)?;
drop((rows, query));
database.close();
Result / 82 B
[
  {
    "name": "Ada"
  },
  {
    "name": "Bob"
  },
  {
    "name": "Cy"
  }
]

Standard JSON values

Any value that the standard JSON encoder of your language accepts also converts here, and decode reads back what encode writes: encoding/json in Go, json.dumps in Python, serde_json in Rust, cheshire or data.json in Clojure and core:encoding/json in Odin. Native tags come first, so instants, durations and links become #utc, #dur and #link values instead of JSON text. Several languages accept more, such as Python sets and UUIDs, or Clojure java.time values. A value is refused only where that encoder refuses it, or where a document cannot hold it: a non-finite number, an integer outside i64, a decimal, instant or duration without an exact native form, or a cycle. The host mapping gives each type.

Ownership and errors

Encode returns a new owned document that holds a snapshot of the value. Close it as you close any document. Decode borrows a document only for the call and returns independent values. It never closes or keeps the document. Typed row iteration borrows the rows and reads one page at a time. Close the rows yourself. Every page of one cursor reads the same store snapshot, so iteration never repeats the query.

Encode, decode and value-argument operations run synchronously. They borrow their input for the duration of the call. A document passes through without copying. A language value becomes a temporary document that closes after the native operation, on success and failure. Drop or close releases owners immediately.

A conversion failure is invalid_argument with a code and a value path such as people[1].age. A failed decode returns no partly filled value.

Costs

Encode and decode copy every value. A document that you pass directly is not copied. Type inspection belongs only to the typed layer, and each language keeps per-type plans where it inspects types at run time. No conversion writes or reads DUST, EDN or TRON text, and JSON text appears only where a Go value supplies its own MarshalJSON or UnmarshalJSON method. Those formats are optional boundaries, not an intermediate transport.

The conversion rules and the host mapping below give each type, the null and missing-field rules and the strict mode.

Operations

OperationReturnsSummary
from_valuedocumentfrom_value(value) copies host values into an owned document.
Document::to_valuevaluedocument.to_value() copies a document into host values.

from_value

rust52 B
pub fn from_value(value: &Value) -> Result<Document>

Parameters

ParameterTypeOwnershipDefaultMeaning
value&ValueValueRequiredA host value to copy into native document nodes.

Errors

StatusWhen
Status::INVALID_ARGUMENTthe value has a host type with no document form (one the language's standard JSON encoder also refuses), a number outside i64 or finite f64, a decimal or time with no exact native form, a failing conversion method, or a cycle
Status::OUT_OF_MEMORYnative memory is exhausted

Notes

Host maps cannot preserve duplicate keys. Use native documents when member order or duplicate keys matter.

Examples

Copy a host integer into a native document

rust62 B
let result = stardust::from_value(&stardust::Value::I64(41))?;
Result / 2 B
41

C exports: stardust_document_builder_create, stardust_document_builder_add_many, stardust_document_builder_seal, stardust_document_builder_error, stardust_document_builder_release

Document::to_value

rust39 B
pub fn to_value(&self) -> Result<Value>

Parameters

ParameterTypeOwnershipDefaultMeaning
self&SelfBorrowed for the callRequiredThe document owner for this operation. Keep it alive during the call.

Errors

Close consumes this owner. Rust ownership prevents later access. Thus, the safe API does not report closed for this receiver.

Notes

Host map semantics determine how duplicate keys are represented. The copied value survives document closure.

Examples

Copy a native input into a host value

input_text holds this document:

json14 B
{
  "x": 41
}
rust130 B
let input = stardust::parse(input_text, Format::JSON)?;
let value = input.to_value()?;
let result = stardust::from_value(&value)?;
Result / 13 B
{
  "x": 41
}

C exports: stardust_document_count, stardust_document_read_many, stardust_document_i64, stardust_document_f64

Typed operations

These helpers convert language values or call native operations. The nesting limit for typed documents is 128 levels.

temporal::serialize

rust118 B
pub fn serialize<T: TimeValue, S: serde::Serializer>(value: &T, serializer: S) -> std::result::Result<S::Ok, S::Error>

temporal::serialize serializes standard Rust time fields, optional values and nested lists as native time tags. Use #[serde(with = "stardust::temporal")]. Generated SDKs select this adapter automatically. The binding's checked tick conversions reject precision loss and values outside the native range. Serde errors retain the field path. Failures: invalid_argument when the value has no document form (a type the language's standard JSON encoder also refuses), a number is outside i64 or finite f64, a decimal, instant or duration has no exact native form, a conversion method of the value fails, the nesting exceeds the depth limit, or the value contains a cycle. out_of_memory when native memory is exhausted.

temporal::deserialize

rust119 B
pub fn deserialize<'de, T: TimeValue, D: serde::Deserializer<'de>>(deserializer: D) -> std::result::Result<T, D::Error>

temporal::deserialize deserializes native time tags into standard Rust time fields, optional values and nested lists. Use #[serde(with = "stardust::temporal")]. Generated SDKs select this adapter automatically. The binding's checked tick conversions reject precision loss and values outside the host range. Serde errors retain the field path. Failures: invalid_argument when the value has no document form (a type the language's standard JSON encoder also refuses), a number is outside i64 or finite f64, a decimal, instant or duration has no exact native form, a conversion method of the value fails, the nesting exceeds the depth limit, or the value contains a cycle. out_of_memory when native memory is exhausted.

duration_from_ticks

rust69 B
pub fn duration_from_ticks(ticks: i64) -> Result<std::time::Duration>

duration_from_ticks(ticks) converts signed native 100 ns ticks to the language's standard duration. This conversion performs no native call. Precision loss and values outside the host range fail. Negative ticks fail because std::time::Duration is unsigned. Failures: invalid_argument when the value has the wrong type, loses precision or exceeds the target range.

duration_to_ticks

rust67 B
pub fn duration_to_ticks(value: std::time::Duration) -> Result<i64>

duration_to_ticks(duration) converts a standard duration to signed native 100 ns ticks. This conversion performs no native call. Precision loss and values outside the native range fail instead of truncating or saturating. Failures: invalid_argument when the value has the wrong type, loses precision or exceeds the target range.

instant_from_ticks

rust70 B
pub fn instant_from_ticks(ticks: i64) -> Result<std::time::SystemTime>

instant_from_ticks(ticks) converts signed native 100 ns ticks since the Unix epoch to the language's standard timestamp. This conversion performs no native call. Precision loss and values outside the host range fail. Failures: invalid_argument when the value has the wrong type, loses precision or exceeds the target range.

instant_to_ticks

rust68 B
pub fn instant_to_ticks(value: std::time::SystemTime) -> Result<i64>

instant_to_ticks(instant) converts a standard timestamp to signed native 100 ns ticks since the Unix epoch. This conversion performs no native call. Precision loss and values outside the native range fail. Failures: invalid_argument when the value has the wrong type, loses precision or exceeds the target range.

decode_time

rust84 B
pub fn decode_time<T>(document: &Document) -> Result<T> where T: temporal::TimeValue

decode_time(document) decodes a native time value into a standard Rust timestamp or duration. Optional values and nested lists use the same checked conversion. The document remains borrowed and its caller closes it. Failures: invalid_argument when a node does not match the target type, a number is outside the target range or, as an integer, has no exact form in it, a text does not parse as the target or its key type, a union has several matching variants, a conversion method of the target fails, an object repeats a key or, where a strict mode is offered and on, has an undeclared key. Narrow floating targets round to nearest. closed when the source is closed.

run_query_values

rust189 B
pub fn run_query_values<T: DeserializeOwned>(query: Query, parameters: Option<&(impl Argument + ?Sized)>, options: &RunOptions, explain: Option<&mut QueryExplain>) -> Result<OwnedValues<T>>

run_query_values(query, parameters, options) takes ownership of a query and runs it with a borrowed language value or document. A language value is encoded into a temporary document that closes after the run on success and failure. The returned owned iterator decodes one native page at a time, closes each page after reading, and releases the query and rows on exhaustion, the first error or early drop. Call close to finish early cleanup. The database must remain open while advancing the cursor. Returned rows own their data; errors retain the field path. It calls the low-level run operation. Failures: those of encode for a language value, then those of the low-level operation.

Utc::serialize

rust122 B
pub fn serialize<S: ser::Serializer>(value: &std::time::SystemTime, serializer: S) -> std::result::Result<S::Ok, S::Error>

Utc::serialize serializes a standard Rust SystemTime field as a native UTC instant. Use #[serde(with = "stardust::Utc")]. Only whole 100 ns ticks in the signed i64 range are accepted. Adapter errors carry the field path. Failures: invalid_argument when the value has no document form (a type the language's standard JSON encoder also refuses), a number is outside i64 or finite f64, a decimal, instant or duration has no exact native form, a conversion method of the value fails, the nesting exceeds the depth limit, or the value contains a cycle. out_of_memory when native memory is exhausted.

Utc::deserialize

rust122 B
pub fn deserialize<'de, D: de::Deserializer<'de>>(deserializer: D) -> std::result::Result<std::time::SystemTime, D::Error>

Utc::deserialize deserializes a native UTC instant into a standard Rust SystemTime field. Use #[serde(with = "stardust::Utc")]. Instants before the epoch retain their sign; values outside the platform time range fail with the field path. Failures: invalid_argument when the value has no document form (a type the language's standard JSON encoder also refuses), a number is outside i64 or finite f64, a decimal, instant or duration has no exact native form, a conversion method of the value fails, the nesting exceeds the depth limit, or the value contains a cycle. out_of_memory when native memory is exhausted.

Dur::serialize

rust120 B
pub fn serialize<S: ser::Serializer>(value: &std::time::Duration, serializer: S) -> std::result::Result<S::Ok, S::Error>

Dur::serialize serializes a standard Rust Duration field as a native duration. Use #[serde(with = "stardust::Dur")]. Only whole 100 ns ticks in the signed i64 range are accepted. Adapter errors carry the field path. Failures: invalid_argument when the value has no document form (a type the language's standard JSON encoder also refuses), a number is outside i64 or finite f64, a decimal, instant or duration has no exact native form, a conversion method of the value fails, the nesting exceeds the depth limit, or the value contains a cycle. out_of_memory when native memory is exhausted.

Dur::deserialize

rust120 B
pub fn deserialize<'de, D: de::Deserializer<'de>>(deserializer: D) -> std::result::Result<std::time::Duration, D::Error>

Dur::deserialize deserializes a native duration into a standard Rust Duration field. Use #[serde(with = "stardust::Dur")]. Negative durations fail because the standard type is unsigned; use Dur for signed native fidelity. Adapter errors carry the field path. Failures: invalid_argument when the value has no document form (a type the language's standard JSON encoder also refuses), a number is outside i64 or finite f64, a decimal, instant or duration has no exact native form, a conversion method of the value fails, the nesting exceeds the depth limit, or the value contains a cycle. out_of_memory when native memory is exhausted.

encode

rust67 B
pub fn encode<T: Serialize + ?Sized>(value: &T) -> Result<Document>

encode(value) copies a language value into a new owned document that holds an immutable snapshot. The caller closes it. Conversion walks the value directly into one preorder builder batch and serializes no text; only a Go json.Marshaler's JSON output is parsed, by the native JSON codec. Failures carry the value path, such as people[3].age, and leave no document: the temporary builder always closes. Failures: invalid_argument when the value has no document form (a type the language's standard JSON encoder also refuses), a number is outside i64 or finite f64, a decimal, instant or duration has no exact native form, a conversion method of the value fails, the nesting exceeds the depth limit, or the value contains a cycle. out_of_memory when native memory is exhausted.

decode

rust68 B
pub fn decode<T: DeserializeOwned>(document: &Document) -> Result<T>

decode(document, type) copies a document into an independent language value of the requested type. It borrows the document only for the call and never closes or retains it. Reads use bounded bulk node reads. A failure reports the value path and returns no partially filled value. Typed objects refuse duplicate keys; unknown keys are ignored unless strict mode is on. A missing field keeps the language default; explicit null needs a nullable target. Failures: invalid_argument when a node does not match the target type, a number is outside the target range or, as an integer, has no exact form in it, a text does not parse as the target or its key type, a union has several matching variants, a conversion method of the target fails, an object repeats a key or, where a strict mode is offered and on, has an undeclared key. Narrow floating targets round to nearest. closed when the source is closed.

Rows::values

rust62 B
pub fn values<T: DeserializeOwned>(&mut self) -> Values<'_, T>

values(rows, type) lazily decodes the rows of a query cursor one at a time, reading one native page at a time. It borrows the rows and never closes them: close the rows yourself. Each internally read page closes when iteration advances, ends, fails or stops early. All pages read the snapshot of the run that created the cursor, so typed iteration never requeries between pages. A failure is reported once, and then iteration ends. Failures: invalid_argument when a node does not match the target type, a number is outside the target range or, as an integer, has no exact form in it, a text does not parse as the target or its key type, a union has several matching variants, a conversion method of the target fails, an object repeats a key or, where a strict mode is offered and on, has an undeclared key. Narrow floating targets round to nearest. closed when the source is closed.

build_value

rust112 B
pub fn build_value(expression: &(impl Argument + ?Sized), explain: Option<&mut BuildExplain>) -> Result<Program>

build_value(expression) accepts a language value or a borrowed document in place of the document argument of the low-level operation. A document is passed through unchanged. A language value is encoded into a temporary document, the low-level operation runs once, and the temporary document closes on success and failure. A string is a string value; it is never parsed as text. The result is the low-level operation's native owner or record. It calls the low-level build operation. Failures: those of encode for a language value, then those of the low-level operation.

evaluate_value

rust137 B
pub fn evaluate_value(program: &Program, input: Option<&(impl Argument + ?Sized)>, explain: Option<&mut EvalExplain>) -> Result<Document>

evaluate_value(program, input) accepts a language value or a borrowed document in place of the document argument of the low-level operation. A document is passed through unchanged. A language value is encoded into a temporary document, the low-level operation runs once, and the temporary document closes on success and failure. A string is a string value; it is never parsed as text. The result is the low-level operation's native owner or record. It calls the low-level evaluate operation. Failures: those of encode for a language value, then those of the low-level operation.

query_value

rust95 B
pub fn query_value(database: &Database, definition: &(impl Argument + ?Sized)) -> Result<Query>

query_value(database, definition) accepts a language value or a borrowed document in place of the document argument of the low-level operation. A document is passed through unchanged. A language value is encoded into a temporary document, the low-level operation runs once, and the temporary document closes on success and failure. A string is a string value; it is never parsed as text. The result is the low-level operation's native owner or record. It calls the low-level query operation. Failures: those of encode for a language value, then those of the low-level operation.

expression_value

rust138 B
pub fn expression_value(database: &Database, definition: &(impl Argument + ?Sized), explain: Option<&mut BuildExplain>) -> Result<Program>

expression_value(database, definition) accepts a language value or a borrowed document in place of the document argument of the low-level operation. A document is passed through unchanged. A language value is encoded into a temporary document, the low-level operation runs once, and the temporary document closes on success and failure. A string is a string value; it is never parsed as text. The result is the low-level operation's native owner or record. It calls the low-level expression operation. Failures: those of encode for a language value, then those of the low-level operation.

run_query_value

rust158 B
pub fn run_query_value(query: &Query, parameters: Option<&(impl Argument + ?Sized)>, options: &RunOptions, explain: Option<&mut QueryExplain>) -> Result<Rows>

run_query_value(query, parameters, options) accepts a language value or a borrowed document in place of the document argument of the low-level operation. A document is passed through unchanged. A language value is encoded into a temporary document, the low-level operation runs once, and the temporary document closes on success and failure. A string is a string value; it is never parsed as text. The result is the low-level operation's native owner or record. It calls the low-level run operation. Failures: those of encode for a language value, then those of the low-level operation.

mutation_value

rust101 B
pub fn mutation_value(database: &Database, definition: &(impl Argument + ?Sized)) -> Result<Mutation>

mutation_value(database, definition) accepts a language value or a borrowed document in place of the document argument of the low-level operation. A document is passed through unchanged. A language value is encoded into a temporary document, the low-level operation runs once, and the temporary document closes on success and failure. A string is a string value; it is never parsed as text. The result is the low-level operation's native owner or record. It calls the low-level mutation operation. Failures: those of encode for a language value, then those of the low-level operation.

run_mutation_value

rust172 B
pub fn run_mutation_value(mutation: &Mutation, parameters: Option<&(impl Argument + ?Sized)>, options: &RunOptions, explain: Option<&mut MutationExplain>) -> Result<Commit>

run_mutation_value(mutation, parameters, options) accepts a language value or a borrowed document in place of the document argument of the low-level operation. A document is passed through unchanged. A language value is encoded into a temporary document, the low-level operation runs once, and the temporary document closes on success and failure. A string is a string value; it is never parsed as text. The result is the low-level operation's native owner or record. It calls the low-level run operation. Failures: those of encode for a language value, then those of the low-level operation.

merge_patch_value

rust133 B
pub fn merge_patch_value(database: &Database, patch: &(impl Argument + ?Sized), explain: Option<&mut PatchExplain>) -> Result<Commit>

merge_patch_value(database, patch) accepts a language value or a borrowed document in place of the document argument of the low-level operation. A document is passed through unchanged. A language value is encoded into a temporary document, the low-level operation runs once, and the temporary document closes on success and failure. A string is a string value; it is never parsed as text. The result is the low-level operation's native owner or record. It calls the low-level merge_patch operation. Failures: those of encode for a language value, then those of the low-level operation.

patch_definition_value

rust126 B
pub fn patch_definition_value(database: &Database, kind: &str, path: &str, patch: &(impl Argument + ?Sized)) -> Result<Commit>

patch_definition_value(database, kind, path, patch) accepts a language value or a borrowed document in place of the document argument of the low-level operation. A document is passed through unchanged. A language value is encoded into a temporary document, the low-level operation runs once, and the temporary document closes on success and failure. A string is a string value; it is never parsed as text. The result is the low-level operation's native owner or record. It calls the low-level patch_definition operation. Failures: those of encode for a language value, then those of the low-level operation.

Conversion rules

ValueRule
standardEvery value that the language's standard JSON encoder accepts converts: encoding/json in Go, json.dumps in Python, serde_json in Rust, cheshire or data.json in Clojure and core:encoding/json in Odin. Decode reads back what encode writes. Refusals remain only where that encoder refuses, or where a document cannot hold the value: a non-finite number, an integer outside i64, an inexact decimal, instant or duration, and a cycle.
nullA nullable target (pointer, option, Maybe, nil slice or map, None, nil) accepts null. A non-nullable target refuses it with wrong_kind. Explicit null is not a missing field.
booleanOnly booleans: no truthiness and no number or string coercion.
integerNumbers are i64 or f64. A host integer of any width or signedness converts when it fits i64; a larger one fails with out_of_range, in both directions. Narrower targets are range-checked (out_of_range).
realFinite f64 only; NaN and infinities are refused. An integer decodes into a floating target only when exactly representable, and a real into an integer target only when finite, integral and in range. f32 narrowing refuses overflow and rounds to nearest. An exact decimal (Python Decimal, Clojure BigDecimal) is an i64 when integral and in range, otherwise the f64 of its shortest spelling; any other decimal fails with inexact_number.
textValid UTF-8, copied without normalization. Invalid UTF-8 and unpaired surrogates are refused. A string argument is a string value; it is never parsed as document text. Values that the standard JSON encoder writes as text stay text: UUIDs, dates and times that are not instants, Go TextMarshaler values, and Go and Clojure byte arrays as base64. Text that does not parse as a typed target fails with invalid_value.
arrayOrdered collections, including tuples, sets and Java collections. A fixed-length target needs the exact length (length_mismatch). A nil slice or list encodes null; an allocated empty one encodes an empty array.
objectStruct, record or dataclass fields and maps. Field names follow the standard encoder's tags and embedding rules; Go also matches a key case-insensitively after an exact match, as encoding/json does. Map keys that are not strings become member keys as the standard encoder spells them (decimal integers, true, false, enum names, MarshalText text) and parse back into typed keys. Typed decode refuses a repeated key (duplicate_field); native documents keep both members. Unknown keys are ignored unless strict mode refuses them (unknown_field). A missing field keeps the language default or fails as required (missing_field).
enumEnums use the standard encoder's form: Rust variants as serde represents them, Python Enum members as their value, Odin enums by name. Odin unions write their active variant and decode into the one variant whose shape matches (ambiguous_variant otherwise).
taggedNative tags take priority over any JSON spelling. Links, UTC instants and durations use the native {#link id}, {#utc text} and {#dur text} objects through the Link type and standard-library instant and duration types. Rust uses #[serde(with = "stardust::Utc")] and #[serde(with = "stardust::Dur")] field adapters to select native tags without guessing from record names. Extra types are only for native values that the standard library cannot represent, such as signed Rust durations. An ordinary object is never reinterpreted as a tagged value. A time value that is not a whole number of 100 ns ticks is refused. Direct converters report inexact_number; Rust Serde adapter errors use the custom-hook codes unsupported_type on encode and wrong_kind on decode, with the field path.
hooksConversion methods run as the standard encoder runs them: Go Encoder and Decoder hooks first, then json.Marshaler, encoding.TextMarshaler and their decode methods; Rust Serialize and Deserialize; Odin registered converters. A failing Go JSON or text method fails with hook_failed; other hooks return their own error. Only Go's JSON methods exchange JSON text, through the native JSON codec.
limitsRecursive conversions refuse nesting beyond the depth limit with too_deep. Go and Python untyped decode traverse iteratively and accept deeper documents. Cyclic host values fail with cycle, or too_deep in Clojure. Every failure has status invalid_argument, a code and a value path such as people[3].age or tags["a.b"]. Failed conversions return no partial value or document.

Host mapping

Typed encode and decode, and the untyped from_value and to_value where the language offers them, use this mapping. Each conversion walks values directly; no text format is involved.

ValueHostDocumentBackMeaning
nullValue::NullnullValue::NullNull retains its value.
integerValue::I64i64Value::I64Signed integers become i64.
floatValue::F64f64Value::F64The conversion refuses non-finite numbers.
textValue::StringUTF-8 stringValue::StringRust strings contain UTF-8.
arrayValue::ArrayarrayValue::ArrayThe conversion preserves array order.
objectValue::ObjectobjectValue::ObjectThe conversion preserves member order and duplicate keys.
map_keysbool, integer, float, char, unit-variant or newtype keys through serdemember key textthe same key types (decode)Keys use serde_json's spelling; Value keys are strings.
bytesbyte strings (serialize_bytes)array of numbersbyte strings (decode)As serde_json writes them; decode also reads the UTF-8 of a string.
enumenums through serdevariant name or tagged objectthe same enum (decode)Externally, internally, adjacently and untagged representations follow serde.
text_valuestypes that serialize as stringsstringthe same types (decode)Serialize decides the spelling.
decimalno decimal typenot applicablenot applicableserde_json without arbitrary precision has no decimal type.
collectionsVec, sets, tuples and arrays through serdearraythe same types (decode)A fixed-length target needs the exact length.
unsignedu8 to u128 through serdei64u8 to u128 (decode)Values that fit i64 become i64; larger ones fail with out_of_range. Value has no unsigned variant.
non_finiteNaN or infinite f32 or f64refusednot producedserde_json writes them as null; documents refuse them instead of changing the value.
timestd::time::SystemTime, std::time::Duration or stardust::LinkUTC, duration or link tagged objectthe same types (decode)Use #[serde(with = "stardust::Utc")] or #[serde(with = "stardust::Dur")] on standard time fields. Unannotated standard time types keep their serde records. Dur preserves negative durations that the unsigned standard type cannot represent. Values must be whole 100 ns ticks.
to_value_numbersdocument numberi64 or f64Value::I64 or Value::F64The conversion tries typed i64 reads before f64.
duplicate_keysdocument objectduplicate membersall membersObject vectors retain order and duplicates.