-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Full scope search for named references (#1600)
Adds support for default values that are named references. For any property with a default value that is a named reference, a managed struct will return the referenced value until set explicitly. Adds logic that searches for properties by name in any owner of a managed value. This allows conformance expression constraints and default values to reference values by name so long as they are visible in any object in the ownership hierarchy. Previously we only supported referencing values that were siblings. I believe this is the last feature we need to support 100% of the data model semantics used in the Matter specifications (as of Matter 1.4).
- Loading branch information
Showing
18 changed files
with
277 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/** | ||
* @license | ||
* Copyright 2022-2024 Matter.js Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
import { Val } from "#behavior/state/Val.js"; | ||
import { RootSupervisor } from "#behavior/supervision/RootSupervisor.js"; | ||
import { Schema } from "#behavior/supervision/Schema.js"; | ||
import { camelize } from "@matter/general"; | ||
import { ClusterModel, Model, ValueModel } from "@matter/model"; | ||
import { Internal } from "./Internal.js"; | ||
|
||
/** | ||
* Obtain a function that returns a visible property by name from the ownership hierarchy of a managed value. | ||
* | ||
* This supports named lookup of a {@link FieldValue.Reference}. | ||
*/ | ||
export function NameResolver( | ||
supervisor: RootSupervisor, | ||
model: Model | undefined, | ||
name: string, | ||
): ((val: Val) => Val) | undefined { | ||
if (model === undefined) { | ||
return; | ||
} | ||
|
||
// Optimization for root schema | ||
if ( | ||
model === supervisor.schema || | ||
(model.id !== undefined && supervisor.schema.tag === model.tag && supervisor.schema.id === model.id) | ||
) { | ||
if (!supervisor.memberNames.has(name)) { | ||
return; | ||
} | ||
return createDirectResolver(); | ||
} | ||
|
||
// Only structs may provide named properties | ||
if (!(model instanceof ValueModel) || model.effectiveMetatype !== "object") { | ||
return createIndirectResolver(); | ||
} | ||
|
||
// Read directly if the named property is supported by this schema. This is not indexed which is fine because: | ||
// 1. The spec uses this very lightly as of 1.4, and | ||
// 2. We only do this once and only for schema that utilizes this feature | ||
if (supervisor.membersOf(model as Schema).find(model => camelize(model.name, false) === name)) { | ||
return createDirectResolver(); | ||
} | ||
|
||
// Delegate to parent | ||
return createIndirectResolver(); | ||
|
||
/** | ||
* Create a reader that reads from this value. | ||
*/ | ||
function createDirectResolver() { | ||
return (val: Val) => (val as Val.Struct)?.[name]; | ||
} | ||
|
||
/** | ||
* Create a reader that reads from parent. | ||
*/ | ||
function createIndirectResolver() { | ||
const parentSchema = model!.parent; | ||
if (!(parentSchema instanceof ValueModel) && !(parentSchema instanceof ClusterModel)) { | ||
return; | ||
} | ||
|
||
const parentReader = NameResolver(supervisor, parentSchema, name); | ||
if (!parentReader) { | ||
return; | ||
} | ||
|
||
return (val: Val) => { | ||
const parent = (val as Internal.Collection)?.[Internal.reference]?.parent?.owner; | ||
if (parent) { | ||
return parentReader(parent as Val.Collection); | ||
} | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.