add specOrNull delegate

This commit is contained in:
Alexander Nozik 2021-12-18 17:02:17 +03:00
parent 1e97165328
commit 91621864c2
No known key found for this signature in database
GPG Key ID: F7FCF2DD25C71357
2 changed files with 27 additions and 1 deletions

View File

@ -2,6 +2,7 @@
## [Unreleased]
### Added
- Add `specOrNull` delegate to meta and Scheme
### Changed
- `Factory` is now `fun interface` and uses `build` instead of `invoke`. `invoke moved to an extension.

View File

@ -43,7 +43,7 @@ public interface Specification<out T : Any> : ReadOnlySpecification<T> {
*/
public fun <T : Any> MutableMeta.updateWith(
spec: Specification<T>,
action: T.() -> Unit
action: T.() -> Unit,
): T = spec.write(this).apply(action)
@ -82,6 +82,31 @@ public fun <T : Scheme> Scheme.spec(
key: Name? = null,
): ReadWriteProperty<Any?, T> = meta.spec(spec, key)
/**
* A delegate that uses a [Specification] to wrap a child of this provider.
* Returns null if meta with given name does not exist.
*/
public fun <T : Scheme> MutableMeta.specOrNull(
spec: Specification<T>,
key: Name? = null,
): ReadWriteProperty<Any?, T?> = object : ReadWriteProperty<Any?, T?> {
override fun getValue(thisRef: Any?, property: KProperty<*>): T? {
val name = key ?: property.name.asName()
return if (get(name) == null) null else spec.write(getOrCreate(name))
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
val name = key ?: property.name.asName()
if (value == null) remove(name)
else set(name, value.toMeta())
}
}
public fun <T : Scheme> Scheme.specOrNull(
spec: Specification<T>,
key: Name? = null,
): ReadWriteProperty<Any?, T?> = meta.specOrNull(spec, key)
/**
* A delegate that uses a [Specification] to wrap a list of child providers.
* If children are mutable, the changes in list elements are reflected on them.