///|
pub struct AssetIndexEntry {
ordinal : Int
asset : Asset
tag_count : Int
shard : Int
} derive(Debug, Eq)
///|
pub struct AssetIndex {
manifest_name : String
entries : Array[AssetIndexEntry]
shard_count : Int
} derive(Debug, Eq)
///|
pub fn AssetIndex::from_manifest(
manifest : DatasetManifest,
shard_count? : Int = 1,
) -> AssetIndex {
let count = max_i(1, shard_count)
let entries : Array[AssetIndexEntry] = []
for i, asset in manifest.assets {
entries.push({
ordinal: i,
asset,
tag_count: asset.tags.length(),
shard: i % count,
})
}
{ manifest_name: manifest.name, entries, shard_count: count }
}
///|
pub fn AssetIndex::count(self : AssetIndex) -> Int {
self.entries.length()
}
///|
pub fn AssetIndex::shard(self : AssetIndex, shard_id : Int) -> Array[Asset] {
let out : Array[Asset] = []
let id = clamp(shard_id, low=0, high=self.shard_count - 1)
for entry in self.entries {
if entry.shard == id {
out.push(entry.asset)
}
}
out
}
///|
pub fn AssetIndex::find_prefix(
self : AssetIndex,
prefix : String,
) -> Array[Asset] {
let out : Array[Asset] = []
for entry in self.entries {
if starts_with(entry.asset.name, prefix) {
out.push(entry.asset)
}
}
out
}
///|
pub fn AssetIndex::with_tag(self : AssetIndex, tag : String) -> Array[Asset] {
let out : Array[Asset] = []
for entry in self.entries {
for candidate in entry.asset.tags {
if candidate == tag {
out.push(entry.asset)
}
}
}
out
}
///|
pub fn AssetIndex::page(
self : AssetIndex,
offset : Int,
limit : Int,
) -> Array[Asset] {
let out : Array[Asset] = []
let start = clamp(offset, low=0, high=self.entries.length())
let end = min_i(self.entries.length(), start + max_i(0, limit))
for i in start.. Array[String] {
let out : Array[String] = []
for entry in self.entries {
for tag in entry.asset.tags {
if !contains_string(out, tag) {
out.push(tag)
}
}
}
out
}
///|
pub fn AssetIndex::checksum(self : AssetIndex) -> UInt {
let mut checksum : UInt = 2166136261
for entry in self.entries {
checksum = (checksum ^ entry.asset.name.length().reinterpret_as_uint()) *
16777619
checksum = (checksum ^ entry.asset.seed) * 16777619
checksum = (checksum ^ entry.shard.reinterpret_as_uint()) * 16777619
}
checksum
}
///|
fn starts_with(text : String, prefix : String) -> Bool {
if prefix.length() > text.length() {
false
} else {
let mut same = true
for i in 0.. Bool {
for value in values {
if value == target {
return true
}
}
false
}
///|
pub fn assets_to_jsonl(assets : Array[Asset]) -> String {
let sb = StringBuilder()
for asset in assets {
sb.write_string(asset.to_json())
sb.write_char('\n')
}
sb.to_string()
}
///|
pub fn manifest_shards(
manifest : DatasetManifest,
shard_count : Int,
) -> Array[DatasetManifest] {
let count = max_i(1, shard_count)
let out : Array[DatasetManifest] = []
for shard in 0.. DatasetManifest {
let out = DatasetManifest::new(name~)
for manifest in manifests {
for asset in manifest.assets {
out.add(asset)
}
}
out
}
///|
pub fn validate_index(index : AssetIndex) -> ValidationReport {
let report = ValidationReport::new()
if index.shard_count <= 0 {
report.error("asset index must contain at least one shard")
}
for entry in index.entries {
if entry.shard < 0 || entry.shard >= index.shard_count {
report.error("asset index shard id is out of range")
}
if entry.tag_count != entry.asset.tags.length() {
report.error("asset index tag count is stale")
}
}
report
}
///|
pub fn DatasetManifest::index(
self : DatasetManifest,
shard_count : Int,
) -> AssetIndex {
AssetIndex::from_manifest(self, shard_count~)
}