From 694661d7477e4bd1e8d7ec96dcc37742d1b5ca3f Mon Sep 17 00:00:00 2001 From: tv Date: Mon, 2 Nov 2026 11:04:15 +0100 Subject: api: add type casts --- src/document/store.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'src/document/store.rs') diff --git a/src/document/store.rs b/src/document/store.rs index 07f2e1a..9075032 100644 --- a/src/document/store.rs +++ b/src/document/store.rs @@ -107,6 +107,9 @@ pub(crate) enum StoreError { /// wanted (`Writing::retype`). #[error("would change {0}")] Retyping(Retyped), + /// A cast that isn't possible (`cast_path`, `typed::cast`), and why. + #[error("can't cast {} to {}: {why}", .from.name(), .to.name())] + NotCastable { from: Kind, to: Kind, why: String }, /// A read at heads the document doesn't have (`at::At`). #[error("this node doesn't have these heads (yet)")] UnknownHeads, @@ -1055,6 +1058,34 @@ fn counter_at(doc: &impl ReadDoc, parent: &ObjId, prop: Prop) -> Result Result, StoreError> { + let held = read_held(doc, path)?.ok_or(StoreError::NotFound)?; + if held.kind == to { + return Ok(Vec::new()); + } + let not_castable = |why: String| StoreError::NotCastable { + from: held.kind, + to, + why, + }; + let value = held + .value + .as_ref() + .ok_or_else(|| not_castable(format!("{} is cast to nothing", held.kind.name())))?; + let cast = typed::cast(held.kind, value, to, timestamps).map_err(not_castable)?; + write_val_path(doc, path, &cast, Writing::new(false, timestamps, true)) +} + /// Inserts `value` into a list: `path` ends in the index it goes to (the items from /// there on move up one; the list's length appends). An index past the end is /// `PastTheEnd`; a parent that isn't a list `NotAList`; anything but an index there, or -- cgit v1.3.1