a few tweaks
This commit is contained in:
@ -71,7 +71,7 @@ JSPG implements specific extensions to the Draft 2020-12 standard to support the
|
|||||||
|
|
||||||
### 1. Polymorphism & Referencing (`$ref`, `$family`, and Native Types)
|
### 1. Polymorphism & Referencing (`$ref`, `$family`, and Native Types)
|
||||||
|
|
||||||
JSPG replaces the complex, dynamic reference resolution logic of standard JSON Schema (e.g., `$defs`, relative URIs, `$dynamicRef`, `$dynamicAnchor`, `if/then/else`) with a strict, explicitly structured global `$id` system. This powers predictable code generation and blazing-fast runtime validation.
|
JSPG replaces the complex, dynamic reference resolution logic of standard JSON Schema (e.g., `$defs`, relative URIs, `$dynamicRef`, `$dynamicAnchor`, `anyOf`) with a strict, explicitly structured global `$id` system. This powers predictable code generation and blazing-fast runtime validation.
|
||||||
|
|
||||||
#### A. Global `$id` Conventions & Schema Buckets
|
#### A. Global `$id` Conventions & Schema Buckets
|
||||||
Every schema is part of a flat, globally addressable namespace. However, where a schema is defined in the database determines its physical boundaries:
|
Every schema is part of a flat, globally addressable namespace. However, where a schema is defined in the database determines its physical boundaries:
|
||||||
|
|||||||
0
agreego.sql
Normal file
0
agreego.sql
Normal file
@ -121,7 +121,7 @@ impl Database {
|
|||||||
if !visited.insert(current_id.clone()) {
|
if !visited.insert(current_id.clone()) {
|
||||||
break; // Cycle detected
|
break; // Cycle detected
|
||||||
}
|
}
|
||||||
if let Some(ref_str) = &schema.obj.ref_string {
|
if let Some(ref_str) = &schema.obj.r#ref {
|
||||||
current_id = ref_str.clone();
|
current_id = ref_str.clone();
|
||||||
depth += 1;
|
depth += 1;
|
||||||
} else {
|
} else {
|
||||||
@ -136,7 +136,7 @@ impl Database {
|
|||||||
fn collect_descendants(&mut self) {
|
fn collect_descendants(&mut self) {
|
||||||
let mut direct_refs: HashMap<String, Vec<String>> = HashMap::new();
|
let mut direct_refs: HashMap<String, Vec<String>> = HashMap::new();
|
||||||
for (id, schema) in &self.schemas {
|
for (id, schema) in &self.schemas {
|
||||||
if let Some(ref_str) = &schema.obj.ref_string {
|
if let Some(ref_str) = &schema.obj.r#ref {
|
||||||
direct_refs
|
direct_refs
|
||||||
.entry(ref_str.clone())
|
.entry(ref_str.clone())
|
||||||
.or_default()
|
.or_default()
|
||||||
|
|||||||
@ -11,7 +11,7 @@ pub struct SchemaObject {
|
|||||||
#[serde(rename = "$id")]
|
#[serde(rename = "$id")]
|
||||||
pub id: Option<String>,
|
pub id: Option<String>,
|
||||||
#[serde(rename = "$ref")]
|
#[serde(rename = "$ref")]
|
||||||
pub ref_string: Option<String>,
|
pub r#ref: Option<String>,
|
||||||
/*
|
/*
|
||||||
Note: The `Ref` field in the Go struct is a pointer populated by the linker.
|
Note: The `Ref` field in the Go struct is a pointer populated by the linker.
|
||||||
In Rust, we might handle this differently (e.g., separate lookup or Rc/Arc),
|
In Rust, we might handle this differently (e.g., separate lookup or Rc/Arc),
|
||||||
@ -306,7 +306,7 @@ impl<'de> Deserialize<'de> for Schema {
|
|||||||
&& obj.if_.is_none()
|
&& obj.if_.is_none()
|
||||||
&& obj.then_.is_none()
|
&& obj.then_.is_none()
|
||||||
&& obj.else_.is_none()
|
&& obj.else_.is_none()
|
||||||
&& obj.ref_string.is_none()
|
&& obj.r#ref.is_none()
|
||||||
&& obj.family.is_none();
|
&& obj.family.is_none();
|
||||||
|
|
||||||
if is_empty && obj.extensible.is_none() {
|
if is_empty && obj.extensible.is_none() {
|
||||||
|
|||||||
@ -14,7 +14,7 @@ impl<'a> ValidationContext<'a> {
|
|||||||
let current = self.instance;
|
let current = self.instance;
|
||||||
if let Some(obj) = current.as_object() {
|
if let Some(obj) = current.as_object() {
|
||||||
// Entity Bound Implicit Type Validation
|
// Entity Bound Implicit Type Validation
|
||||||
if let Some(lookup_key) = self.schema.id.as_ref().or(self.schema.ref_string.as_ref()) {
|
if let Some(lookup_key) = self.schema.id.as_ref().or(self.schema.r#ref.as_ref()) {
|
||||||
let base_type_name = lookup_key.split('.').next_back().unwrap_or("").to_string();
|
let base_type_name = lookup_key.split('.').next_back().unwrap_or("").to_string();
|
||||||
if let Some(type_def) = self.db.types.get(&base_type_name)
|
if let Some(type_def) = self.db.types.get(&base_type_name)
|
||||||
&& let Some(type_val) = obj.get("type")
|
&& let Some(type_val) = obj.get("type")
|
||||||
@ -99,7 +99,7 @@ impl<'a> ValidationContext<'a> {
|
|||||||
|
|
||||||
if let Some(child_instance) = obj.get(key) {
|
if let Some(child_instance) = obj.get(key) {
|
||||||
let new_path = format!("{}/{}", self.path, key);
|
let new_path = format!("{}/{}", self.path, key);
|
||||||
let is_ref = sub_schema.ref_string.is_some();
|
let is_ref = sub_schema.r#ref.is_some();
|
||||||
let next_extensible = if is_ref { false } else { self.extensible };
|
let next_extensible = if is_ref { false } else { self.extensible };
|
||||||
|
|
||||||
let derived = self.derive(
|
let derived = self.derive(
|
||||||
@ -114,7 +114,7 @@ impl<'a> ValidationContext<'a> {
|
|||||||
|
|
||||||
// Entity Bound Implicit Type Interception
|
// Entity Bound Implicit Type Interception
|
||||||
if key == "type"
|
if key == "type"
|
||||||
&& let Some(lookup_key) = sub_schema.id.as_ref().or(sub_schema.ref_string.as_ref())
|
&& let Some(lookup_key) = sub_schema.id.as_ref().or(sub_schema.r#ref.as_ref())
|
||||||
{
|
{
|
||||||
let base_type_name = lookup_key.split('.').next_back().unwrap_or("").to_string();
|
let base_type_name = lookup_key.split('.').next_back().unwrap_or("").to_string();
|
||||||
if let Some(type_def) = self.db.types.get(&base_type_name)
|
if let Some(type_def) = self.db.types.get(&base_type_name)
|
||||||
@ -138,7 +138,7 @@ impl<'a> ValidationContext<'a> {
|
|||||||
for (key, child_instance) in obj {
|
for (key, child_instance) in obj {
|
||||||
if compiled_re.0.is_match(key) {
|
if compiled_re.0.is_match(key) {
|
||||||
let new_path = format!("{}/{}", self.path, key);
|
let new_path = format!("{}/{}", self.path, key);
|
||||||
let is_ref = sub_schema.ref_string.is_some();
|
let is_ref = sub_schema.r#ref.is_some();
|
||||||
let next_extensible = if is_ref { false } else { self.extensible };
|
let next_extensible = if is_ref { false } else { self.extensible };
|
||||||
|
|
||||||
let derived = self.derive(
|
let derived = self.derive(
|
||||||
@ -177,7 +177,7 @@ impl<'a> ValidationContext<'a> {
|
|||||||
|
|
||||||
if !locally_matched {
|
if !locally_matched {
|
||||||
let new_path = format!("{}/{}", self.path, key);
|
let new_path = format!("{}/{}", self.path, key);
|
||||||
let is_ref = additional_schema.ref_string.is_some();
|
let is_ref = additional_schema.r#ref.is_some();
|
||||||
let next_extensible = if is_ref { false } else { self.extensible };
|
let next_extensible = if is_ref { false } else { self.extensible };
|
||||||
|
|
||||||
let derived = self.derive(
|
let derived = self.derive(
|
||||||
|
|||||||
@ -13,7 +13,7 @@ impl<'a> ValidationContext<'a> {
|
|||||||
|| self.schema.required.is_some()
|
|| self.schema.required.is_some()
|
||||||
|| self.schema.additional_properties.is_some()
|
|| self.schema.additional_properties.is_some()
|
||||||
|| self.schema.items.is_some()
|
|| self.schema.items.is_some()
|
||||||
|| self.schema.ref_string.is_some()
|
|| self.schema.r#ref.is_some()
|
||||||
|| self.schema.one_of.is_some()
|
|| self.schema.one_of.is_some()
|
||||||
|| self.schema.all_of.is_some()
|
|| self.schema.all_of.is_some()
|
||||||
|| self.schema.enum_.is_some()
|
|| self.schema.enum_.is_some()
|
||||||
@ -122,7 +122,7 @@ impl<'a> ValidationContext<'a> {
|
|||||||
result: &mut ValidationResult,
|
result: &mut ValidationResult,
|
||||||
) -> Result<bool, ValidationError> {
|
) -> Result<bool, ValidationError> {
|
||||||
// 1. Core $ref logic relies on the fast O(1) map to allow cycles and proper nesting
|
// 1. Core $ref logic relies on the fast O(1) map to allow cycles and proper nesting
|
||||||
if let Some(ref_str) = &self.schema.ref_string {
|
if let Some(ref_str) = &self.schema.r#ref {
|
||||||
if let Some(global_schema) = self.db.schemas.get(ref_str) {
|
if let Some(global_schema) = self.db.schemas.get(ref_str) {
|
||||||
let mut new_overrides = self.overrides.clone();
|
let mut new_overrides = self.overrides.clone();
|
||||||
if let Some(props) = &self.schema.properties {
|
if let Some(props) = &self.schema.properties {
|
||||||
|
|||||||
Reference in New Issue
Block a user