feat: publish Dever core with project scaffolding and versioned AI skills
This commit is contained in:
1 parent
70fa73cdc2
commit
ac458ffa7f
960 files changed
+221319
-1163
No files matched your search
@@ -0,0 +1,348 @@
|
||||
//! Strict wire boundary. Parsed nodes never escape into generated business signatures.
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::fmt;
|
||||
|
||||
use base64::Engine as _;
|
||||
use serde::Deserializer;
|
||||
use serde::de::{self, MapAccess, SeqAccess, Visitor};
|
||||
use serde_json::value::RawValue;
|
||||
|
||||
pub const MAX_BYTES: usize = 16 * 1024 * 1024;
|
||||
pub const MAX_DEPTH: usize = 64;
|
||||
pub const MAX_ELEMENTS: usize = 65_536;
|
||||
|
||||
pub struct Node<'a> {
|
||||
raw: &'a str,
|
||||
kind: Kind<'a>,
|
||||
}
|
||||
|
||||
enum Kind<'a> {
|
||||
Null,
|
||||
Bool(bool),
|
||||
Number,
|
||||
Text(String),
|
||||
List(Vec<Node<'a>>),
|
||||
Object(BTreeMap<String, Node<'a>>),
|
||||
}
|
||||
|
||||
pub fn parse(text: &str) -> Result<Node<'_>, String> {
|
||||
if text.len() > MAX_BYTES {
|
||||
return Err("wire JSON exceeds byte limit".into());
|
||||
}
|
||||
let raw: &RawValue = serde_json::from_str(text).map_err(|error| error.to_string())?;
|
||||
let mut remaining = MAX_ELEMENTS;
|
||||
parse_node(raw, 0, &mut remaining)
|
||||
}
|
||||
|
||||
fn parse_node<'a>(
|
||||
raw: &'a RawValue,
|
||||
depth: usize,
|
||||
remaining: &mut usize,
|
||||
) -> Result<Node<'a>, String> {
|
||||
if depth > MAX_DEPTH {
|
||||
return Err("wire JSON exceeds depth limit".into());
|
||||
}
|
||||
*remaining = remaining
|
||||
.checked_sub(1)
|
||||
.ok_or("wire JSON exceeds element limit")?;
|
||||
let text = raw.get();
|
||||
let kind = match text.as_bytes()[0] {
|
||||
b'n' => Kind::Null,
|
||||
b't' => Kind::Bool(true),
|
||||
b'f' => Kind::Bool(false),
|
||||
b'"' => Kind::Text(serde_json::from_str(text).map_err(|error| error.to_string())?),
|
||||
b'[' | b'{' => {
|
||||
if depth == MAX_DEPTH {
|
||||
return Err("wire JSON exceeds depth limit".into());
|
||||
}
|
||||
let mut decoder = serde_json::Deserializer::from_str(text);
|
||||
let kind = decoder
|
||||
.deserialize_any(Container { depth, remaining })
|
||||
.map_err(|error| error.to_string())?;
|
||||
decoder.end().map_err(|error| error.to_string())?;
|
||||
kind
|
||||
}
|
||||
_ => Kind::Number,
|
||||
};
|
||||
Ok(Node { raw: text, kind })
|
||||
}
|
||||
|
||||
struct Container<'b> {
|
||||
depth: usize,
|
||||
remaining: &'b mut usize,
|
||||
}
|
||||
|
||||
impl<'de> Visitor<'de> for Container<'_> {
|
||||
type Value = Kind<'de>;
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter.write_str("a bounded JSON container")
|
||||
}
|
||||
fn visit_seq<A: SeqAccess<'de>>(self, mut sequence: A) -> Result<Self::Value, A::Error> {
|
||||
let mut values = Vec::new();
|
||||
while let Some(raw) = sequence.next_element::<&'de RawValue>()? {
|
||||
values
|
||||
.push(parse_node(raw, self.depth + 1, self.remaining).map_err(de::Error::custom)?);
|
||||
}
|
||||
Ok(Kind::List(values))
|
||||
}
|
||||
fn visit_map<A: MapAccess<'de>>(self, mut object: A) -> Result<Self::Value, A::Error> {
|
||||
let mut values = BTreeMap::new();
|
||||
while let Some(key) = object.next_key::<String>()? {
|
||||
if values.contains_key(&key) {
|
||||
return Err(de::Error::custom("duplicate JSON field"));
|
||||
}
|
||||
let raw = object.next_value::<&'de RawValue>()?;
|
||||
values.insert(
|
||||
key,
|
||||
parse_node(raw, self.depth + 1, self.remaining).map_err(de::Error::custom)?,
|
||||
);
|
||||
}
|
||||
Ok(Kind::Object(values))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Node<'a> {
|
||||
pub fn bytes(&self) -> Result<crate::bytes::Bytes, String> {
|
||||
base64::engine::general_purpose::STANDARD
|
||||
.decode(self.text()?)
|
||||
.map(crate::bytes::Bytes::new)
|
||||
.map_err(|_| "invalid wire Bytes base64".into())
|
||||
}
|
||||
|
||||
pub fn is_null(&self) -> bool {
|
||||
matches!(self.kind, Kind::Null)
|
||||
}
|
||||
pub fn raw(&self) -> &'a str {
|
||||
self.raw
|
||||
}
|
||||
pub fn text(&self) -> Result<&str, String> {
|
||||
match &self.kind {
|
||||
Kind::Text(value) => Ok(value),
|
||||
_ => Err("expected wire string".into()),
|
||||
}
|
||||
}
|
||||
pub fn boolean(&self) -> Result<bool, String> {
|
||||
match self.kind {
|
||||
Kind::Bool(value) => Ok(value),
|
||||
_ => Err("expected wire Bool".into()),
|
||||
}
|
||||
}
|
||||
pub fn int(&self) -> Result<i64, String> {
|
||||
if !matches!(self.kind, Kind::Number) {
|
||||
return Err("expected wire integer".into());
|
||||
}
|
||||
self.raw
|
||||
.parse()
|
||||
.map_err(|_| "wire integer is not an exact i64".into())
|
||||
}
|
||||
pub fn float(&self) -> Result<f64, String> {
|
||||
if !matches!(self.kind, Kind::Number) {
|
||||
return Err("expected wire Float".into());
|
||||
}
|
||||
let value: f64 = self.raw.parse().map_err(|_| "invalid wire Float")?;
|
||||
if !value.is_finite() {
|
||||
return Err("non-finite wire Float".into());
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
pub fn list(&self) -> Result<&[Node<'a>], String> {
|
||||
match &self.kind {
|
||||
Kind::List(values) => Ok(values),
|
||||
_ => Err("expected wire List".into()),
|
||||
}
|
||||
}
|
||||
pub fn fields(&self, names: &[&str]) -> Result<&BTreeMap<String, Node<'a>>, String> {
|
||||
let fields = self.object()?;
|
||||
if fields.keys().any(|name| !names.contains(&name.as_str())) {
|
||||
return Err("unknown wire record field".into());
|
||||
}
|
||||
Ok(fields)
|
||||
}
|
||||
pub fn object(&self) -> Result<&BTreeMap<String, Node<'a>>, String> {
|
||||
match &self.kind {
|
||||
Kind::Object(fields) => Ok(fields),
|
||||
_ => Err("expected wire record".into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Only validated JSON can be placed in an API envelope without re-encoding its numbers.
|
||||
pub struct Encoded(String);
|
||||
impl Encoded {
|
||||
pub fn as_str(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
pub fn null() -> Self {
|
||||
Self("null".into())
|
||||
}
|
||||
}
|
||||
|
||||
enum Frame {
|
||||
Array(usize),
|
||||
Object {
|
||||
names: BTreeSet<String>,
|
||||
awaiting_value: bool,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Encoder {
|
||||
output: String,
|
||||
stack: Vec<Frame>,
|
||||
elements: usize,
|
||||
failed: bool,
|
||||
}
|
||||
|
||||
impl Encoder {
|
||||
pub fn bytes(&mut self, value: &crate::bytes::Bytes) -> Result<(), String> {
|
||||
let length = base64::encoded_len(value.values().len(), true)
|
||||
.and_then(|length| length.checked_add(2))
|
||||
.ok_or("wire JSON exceeds byte limit")?;
|
||||
if length > MAX_BYTES.saturating_sub(self.output.len()) {
|
||||
return Err("wire JSON exceeds byte limit".into());
|
||||
}
|
||||
self.text(&base64::engine::general_purpose::STANDARD.encode(value.values()))
|
||||
}
|
||||
|
||||
fn append(&mut self, text: &str) -> Result<(), String> {
|
||||
if text.len() > MAX_BYTES.saturating_sub(self.output.len()) {
|
||||
// Frame bookkeeping may already have advanced before an append fails.
|
||||
// Such a partial write must never become a validated Encoded value.
|
||||
self.failed = true;
|
||||
return Err("wire JSON exceeds byte limit".into());
|
||||
}
|
||||
self.output.push_str(text);
|
||||
Ok(())
|
||||
}
|
||||
fn value(&mut self) -> Result<(), String> {
|
||||
if self.elements == MAX_ELEMENTS {
|
||||
return Err("wire JSON exceeds element limit".into());
|
||||
}
|
||||
self.elements += 1;
|
||||
let comma = match self.stack.last_mut() {
|
||||
Some(Frame::Array(count)) => {
|
||||
*count += 1;
|
||||
*count > 1
|
||||
}
|
||||
Some(Frame::Object { awaiting_value, .. }) if *awaiting_value => {
|
||||
*awaiting_value = false;
|
||||
false
|
||||
}
|
||||
Some(Frame::Object { .. }) => return Err("wire object requires a field name".into()),
|
||||
None if self.elements != 1 => return Err("wire JSON has multiple roots".into()),
|
||||
None => false,
|
||||
};
|
||||
if comma {
|
||||
self.append(",")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn null(&mut self) -> Result<(), String> {
|
||||
self.scalar("null")
|
||||
}
|
||||
pub fn boolean(&mut self, value: bool) -> Result<(), String> {
|
||||
self.scalar(if value { "true" } else { "false" })
|
||||
}
|
||||
pub fn int(&mut self, value: i64) -> Result<(), String> {
|
||||
self.scalar(&value.to_string())
|
||||
}
|
||||
pub fn float(&mut self, value: f64) -> Result<(), String> {
|
||||
if !value.is_finite() {
|
||||
return Err("non-finite wire Float".into());
|
||||
}
|
||||
self.scalar(&serde_json::to_string(&value).map_err(|error| error.to_string())?)
|
||||
}
|
||||
pub fn text(&mut self, value: &str) -> Result<(), String> {
|
||||
if value.len() > MAX_BYTES.saturating_sub(self.output.len()) {
|
||||
return Err("wire JSON exceeds byte limit".into());
|
||||
}
|
||||
self.scalar(&serde_json::to_string(value).map_err(|error| error.to_string())?)
|
||||
}
|
||||
fn scalar(&mut self, text: &str) -> Result<(), String> {
|
||||
self.value()?;
|
||||
self.append(text)
|
||||
}
|
||||
pub fn json(&mut self, text: &str) -> Result<(), String> {
|
||||
if text.len() > MAX_BYTES.saturating_sub(self.output.len()) {
|
||||
return Err("wire JSON exceeds byte limit".into());
|
||||
}
|
||||
let raw: &RawValue = serde_json::from_str(text).map_err(|error| error.to_string())?;
|
||||
let mut remaining = MAX_ELEMENTS - self.elements;
|
||||
parse_node(raw, self.stack.len(), &mut remaining)?;
|
||||
self.value()?;
|
||||
self.elements = MAX_ELEMENTS - remaining;
|
||||
self.append(raw.get())
|
||||
}
|
||||
pub fn begin_array(&mut self) -> Result<(), String> {
|
||||
self.begin(false)
|
||||
}
|
||||
pub fn begin_object(&mut self) -> Result<(), String> {
|
||||
self.begin(true)
|
||||
}
|
||||
fn begin(&mut self, object: bool) -> Result<(), String> {
|
||||
if self.stack.len() >= MAX_DEPTH {
|
||||
return Err("wire JSON exceeds depth limit".into());
|
||||
}
|
||||
self.value()?;
|
||||
self.append(if object { "{" } else { "[" })?;
|
||||
self.stack.push(if object {
|
||||
Frame::Object {
|
||||
names: BTreeSet::new(),
|
||||
awaiting_value: false,
|
||||
}
|
||||
} else {
|
||||
Frame::Array(0)
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
pub fn key(&mut self, name: &str) -> Result<(), String> {
|
||||
if name.len() > MAX_BYTES.saturating_sub(self.output.len()) {
|
||||
return Err("wire JSON exceeds byte limit".into());
|
||||
}
|
||||
let Some(Frame::Object {
|
||||
names,
|
||||
awaiting_value,
|
||||
}) = self.stack.last_mut()
|
||||
else {
|
||||
return Err("wire field outside record".into());
|
||||
};
|
||||
if *awaiting_value {
|
||||
return Err("wire field has no value".into());
|
||||
}
|
||||
if !names.insert(name.to_owned()) {
|
||||
return Err("duplicate JSON field".into());
|
||||
}
|
||||
*awaiting_value = true;
|
||||
let comma = names.len() > 1;
|
||||
if comma {
|
||||
self.append(",")?;
|
||||
}
|
||||
self.append(&serde_json::to_string(name).map_err(|error| error.to_string())?)?;
|
||||
self.append(":")
|
||||
}
|
||||
pub fn end(&mut self) -> Result<(), String> {
|
||||
if matches!(
|
||||
self.stack.last(),
|
||||
Some(Frame::Object {
|
||||
awaiting_value: true,
|
||||
..
|
||||
})
|
||||
) {
|
||||
return Err("incomplete wire container".into());
|
||||
}
|
||||
match self.stack.pop() {
|
||||
Some(Frame::Array(_)) => self.append("]"),
|
||||
Some(Frame::Object {
|
||||
awaiting_value: false,
|
||||
..
|
||||
}) => self.append("}"),
|
||||
_ => Err("incomplete wire container".into()),
|
||||
}
|
||||
}
|
||||
pub fn finish(self) -> Result<Encoded, String> {
|
||||
if self.failed || !self.stack.is_empty() || self.elements == 0 {
|
||||
return Err("incomplete wire JSON".into());
|
||||
}
|
||||
Ok(Encoded(self.output))
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user