use crate::registry::compile::parse::{
AuthorityDefinition as AuthorityTomlDefinition, NamespaceDefinition as NamespaceTomlDefinition,
PkgDefinition as PkgTomlDefinition, PkgVersion, RegistryDefinition as RegistryTomlDefinition,
RegistryHistoryDefinition as RegistryHistoryTomlDefinition,
};
use crate::registry::schema::registry::{Registry, RegistryDefinition, RegistryHistoryDefinition};
use crate::registry::schema::registry_generated::registry::{
AuthorityDefinition, AuthorityDefinitionArgs, RegistryArgs, RegistryDefinitionArgs,
RegistryHistoryDefinitionArgs, RegistryRefType,
};
use crate::registry::schema::registry_generated::registry::RegistryRefType as RegistryRefType2;
use flatbuffers::{FlatBufferBuilder, WIPOffset};
pub fn compile_registry(
authorities: Vec<&AuthorityTomlDefinition>,
namespaces: Vec<&NamespaceTomlDefinition>,
pkgs: Vec<&PkgTomlDefinition>,
) -> Vec<u8> {
let mut builder = FlatBufferBuilder::new();
let authority_offsets = authorities
.into_iter()
.map(|a| compile_authority(&mut builder, a))
.collect::<Vec<_>>();
let authorities = builder.create_vector(&authority_offsets);
let namespace_offsets = namespaces
.into_iter()
.map(|n| compile_namespace(&mut builder, n))
.collect::<Vec<_>>();
let namespaces = builder.create_vector(&namespace_offsets);
let package_offsets = pkgs
.into_iter()
.map(|p| compile_pkg_registry_entry(&mut builder, p))
.collect::<Vec<_>>();
let packages = builder.create_vector(&package_offsets);
let root = Registry::create(
&mut builder,
&RegistryArgs {
authorities: Some(authorities),
namespaces: Some(namespaces),
packages: Some(packages),
},
);
builder.finish(root, None);
builder.finished_data().to_vec()
}
use crate::registry::schema::registry::{Namespace, NamespaceArgs};
use crate::registry::schema::registry::{PkgRegistryEntry, PkgRegistryEntryArgs};
fn compile_pkg_registry_entry<'a>(
builder: &mut FlatBufferBuilder<'a>,
pkg: &PkgTomlDefinition,
) -> WIPOffset<PkgRegistryEntry<'a>> {
let name = builder.create_string(&pkg.metadata.name);
let authority = builder.create_string(&pkg.metadata.authority);
let reference = builder.create_string(&pkg.metadata.reference);
let versions = pkg
.versions
.iter()
.map(|v| compile_version(builder, v))
.collect::<Vec<_>>();
let versions = builder.create_vector(&versions);
PkgRegistryEntry::create(
builder,
&PkgRegistryEntryArgs {
name: Some(name),
authority: Some(authority),
ref_type: RegistryRefType::NoRef,
ref_: Some(reference),
use_ref: !pkg.metadata.reference.is_empty(),
versions: Some(versions),
},
)
}
use crate::registry::schema::registry::{Hash, Version, VersionArgs};
fn compile_version<'a>(
builder: &mut FlatBufferBuilder<'a>,
version: &PkgVersion,
) -> WIPOffset<Version<'a>> {
let tag = builder.create_string("");
let (major, minor, patch, tag_name) = parse_version(&version.version);
let tag = if tag_name.is_empty() {
None
} else {
Some(builder.create_string(&tag_name))
};
let hash = compile_hash(builder, &version.hash);
Version::create(
builder,
&VersionArgs {
major,
minor,
patch,
tag,
hash: Some(&hash),
date: parse_date(&version.date),
},
)
}
fn parse_version(version: &str) -> (u16, u8, u8, String) {
let mut tag = String::new();
let mut split = version.splitn(2, '-');
let numbers = split.next().unwrap_or("0.0.0");
if let Some(t) = split.next() {
tag = t.to_string();
}
let mut nums = numbers.split('.');
let major = nums.next().unwrap_or("0").parse().unwrap_or(0);
let minor = nums.next().unwrap_or("0").parse().unwrap_or(0);
let patch = nums.next().unwrap_or("0").parse().unwrap_or(0);
(major, minor, patch, tag)
}
fn compile_hash(_builder: &mut FlatBufferBuilder, hash: &str) -> Hash {
let hash = hash.trim();
let mut parts = [0u64; 4];
for (i, chunk) in hash.as_bytes().chunks(16).take(4).enumerate() {
let s = std::str::from_utf8(chunk).unwrap_or("0");
parts[i] = u64::from_str_radix(s, 16).unwrap_or(0);
}
Hash::new(parts[0], parts[1], parts[2], parts[3])
}
use chrono::DateTime;
fn parse_date(date: &str) -> u64 {
DateTime::parse_from_rfc3339(date)
.map(|d| d.timestamp() as u64)
.unwrap_or(0)
}
fn compile_namespace<'a>(
builder: &mut FlatBufferBuilder<'a>,
namespace: &NamespaceTomlDefinition,
) -> WIPOffset<Namespace<'a>> {
let id = builder.create_string(&namespace.metadata.id);
let name = builder.create_string(&namespace.metadata.name);
let owners = namespace
.metadata
.owners
.iter()
.map(|owner| builder.create_string(owner))
.collect::<Vec<_>>();
let owners = builder.create_vector(&owners);
Namespace::create(
builder,
&NamespaceArgs {
id: Some(id),
name: Some(name),
owners: Some(owners),
},
)
}
pub fn compile_authority<'a>(
builder: &mut FlatBufferBuilder<'a>,
authority: &AuthorityTomlDefinition,
) -> WIPOffset<AuthorityDefinition<'a>> {
let id = builder.create_string(&authority.metadata.id);
let name = builder.create_string(&authority.metadata.name);
let homepage = builder.create_string(&authority.metadata.homepage);
let description = builder.create_string(&authority.metadata.description);
let owners = authority
.metadata
.owners
.iter()
.map(|owner| builder.create_string(owner))
.collect::<Vec<_>>();
let owners = builder.create_vector(&owners);
let signing_keys = authority
.metadata
.signing_keys
.iter()
.map(|key| builder.create_string(key))
.collect::<Vec<_>>();
let signing_keys = builder.create_vector(&signing_keys);
let registries = authority
.registries
.iter()
.enumerate()
.map(|(id, registry)| compile_registry_definition(builder, id as u16, registry))
.collect::<Vec<_>>();
let registries = builder.create_vector(®istries);
crate::registry::schema::registry::AuthorityDefinition::create(
builder,
&AuthorityDefinitionArgs {
id: Some(id),
name: Some(name),
owners: Some(owners),
homepage: Some(homepage),
description: Some(description),
registries: Some(registries),
signing_keys: Some(signing_keys),
},
)
}
fn compile_registry_definition<'a>(
builder: &mut FlatBufferBuilder<'a>,
id: u16,
registry: &RegistryTomlDefinition,
) -> WIPOffset<RegistryDefinition<'a>> {
let reference = builder.create_string(®istry.reference);
let namespace = builder.create_string(®istry.namespace);
let history = registry
.history
.iter()
.enumerate()
.map(|(id, history)| compile_registry_history(builder, id as u16, history))
.collect::<Vec<_>>();
let history = builder.create_vector(&history);
RegistryDefinition::create(
builder,
&RegistryDefinitionArgs {
id,
type_: parse_registry_ref_type(®istry.registry_type),
ref_: Some(reference),
namespace: Some(namespace),
history: Some(history),
},
)
}
fn compile_registry_history<'a>(
builder: &mut FlatBufferBuilder<'a>,
id: u16,
history: &RegistryHistoryTomlDefinition,
) -> WIPOffset<RegistryHistoryDefinition<'a>> {
let reference = builder.create_string(&history.reference);
RegistryHistoryDefinition::create(
builder,
&RegistryHistoryDefinitionArgs {
id,
type_: parse_registry_ref_type(&history.registry_type),
ref_: Some(reference),
deprecated: history.deprecated,
until: parse_date(&history.until),
},
)
}
pub fn parse_registry_ref_type(ty: &str) -> RegistryRefType {
match ty.to_ascii_lowercase().as_str() {
"github" => RegistryRefType::Github,
"http" => RegistryRefType::HTTP,
"inregistry" => RegistryRefType::InRegistry,
_ => RegistryRefType::NoRef,
}
}