use num_bigint::{ BigUint, BigInt };
use num_traits::{Zero, One};
use std::collections::{HashMap, HashSet};
use std::fmt;
use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
use lazy_static::lazy_static;
use std::marker::PhantomData;
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
pub struct PackageName {
pub package: Vec<String>,
}
impl PackageName {
pub fn new() -> PackageName {
PackageName {
package: Vec::new(),
}
}
pub fn from_str(pkg: &str) -> PackageName {
PackageName {
package:
if pkg.is_empty() {
Vec::new()
}
else {
pkg.split(".").map(str::to_string).collect()
},
}
}
pub fn from_parts(parts: &[&str]) -> PackageName {
PackageName {
package: parts.iter().map(|x| String::from(*x)).collect::<Vec<_>>(),
}
}
}
impl fmt::Display for PackageName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for_sep!(item, &self.package, { write!(f, ".")?; }, {
write!(f, "{}", item)?;
});
Ok(())
}
}
impl Ord for PackageName {
fn cmp(&self, other: &Self) -> Ordering {
let mut i1 = self.package.iter();
let mut i2 = other.package.iter();
loop {
match (i1.next(), i2.next()) {
(Some(p1), Some(p2)) => {
let ord = p1.cmp(p2);
if ord != Ordering::Equal {
return ord
}
},
(Some(_), None) => return Ordering::Greater,
(None, Some(_)) => return Ordering::Less,
(None, None) => return Ordering::Equal,
}
}
}
}
impl PartialOrd for PackageName {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
pub struct QualifiedName {
pub package: PackageName,
pub name: String,
}
impl QualifiedName {
pub fn from_str(name: &str) -> Option<QualifiedName> {
let mut iter = name.split(".");
if let Some(part) = iter.next() {
let mut pkg_parts = Vec::new();
let mut name = String::from(part);
while let Some(part) = iter.next() {
pkg_parts.push(name);
name = String::from(part);
}
Some(QualifiedName {
package: PackageName {
package: pkg_parts,
},
name: name,
})
}
else {
None
}
}
pub fn from_parts(package: &[&str], name: &str) -> QualifiedName {
QualifiedName {
package: PackageName::from_parts(package),
name: String::from(name),
}
}
}
impl fmt::Display for QualifiedName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.package.package.is_empty() {
write!(f, "{}", self.name)
}
else {
write!(f, "{}.{}", self.package, self.name)
}
}
}
impl Ord for QualifiedName {
fn cmp(&self, other: &Self) -> Ordering {
let ord = self.package.cmp(&other.package);
if ord != Ordering::Equal {
return ord
}
self.name.cmp(&other.name)
}
}
impl PartialOrd for QualifiedName {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[derive(Debug)]
pub enum ModelError {
DuplicateConstant(QualifiedName),
DuplicateType(QualifiedName),
DuplicateVersion(QualifiedName, BigUint),
DuplicateField(QualifiedName, BigUint, String),
DuplicateLiteralInteger(QualifiedName),
DuplicateLiteralString(QualifiedName),
DuplicateLiteralSequence(QualifiedName),
DuplicateLiteralCase(QualifiedName, String),
DuplicateLiteralRecord(QualifiedName),
DuplicateLiteralRecordField(QualifiedName, String),
DuplicateFieldValue(String),
}
impl fmt::Display for ModelError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ModelError::DuplicateConstant(name) => write!(f, "Cannot declare constant {}. Name is already defined.", name),
ModelError::DuplicateType(name) => write!(f, "Cannot declare type {}. Name is already defined.", name),
ModelError::DuplicateVersion(name, version) => write!(f, "Version {} of type {} is already defined.", version, name),
ModelError::DuplicateField(name, version, field) => write!(f, "Version {} of type {} already has a field named {}.", version, name, field),
ModelError::DuplicateLiteralInteger(type_name) => write!(f, "Type {} already has an integer literal.", type_name),
ModelError::DuplicateLiteralString(type_name) => write!(f, "Type {} already has a string literal.", type_name),
ModelError::DuplicateLiteralSequence(type_name) => write!(f, "Type {} already has a sequence literal.", type_name),
ModelError::DuplicateLiteralCase(type_name, name) => write!(f, "Type {} already has a literal for case {}.", type_name, name),
ModelError::DuplicateLiteralRecord(type_name) => write!(f, "Type {} already has a record literal.", type_name),
ModelError::DuplicateLiteralRecordField(type_name, field) => write!(f, "Record literal for type {} already has a field named {}.", type_name, field),
ModelError::DuplicateFieldValue(name) => write!(f, "Record constant already has a field named {}.", name),
}
}
}
#[derive(Clone, Debug)]
pub struct Type {
pub name: QualifiedName,
pub args: Vec<Type>,
}
pub struct Named<'a, A> {
model: &'a Verilization,
name: &'a QualifiedName,
value: &'a A,
}
impl <'a, A: fmt::Debug> fmt::Debug for Named<'a, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_struct("Named")
.field("name", &self.name)
.field("value", &self.value)
.finish()
}
}
impl <'a, A> Clone for Named<'a, A> {
fn clone(&self) -> Self {
Named {
model: self.model,
name: self.name,
value: self.value,
}
}
}
impl <'a, A> Copy for Named<'a, A> {}
impl <'a, A> Named<'a, A> {
fn new(model: &'a Verilization, name: &'a QualifiedName, value: &'a A) -> Named<'a, A> {
Named {
model: model,
name: name,
value: value,
}
}
pub fn name(&self) -> &'a QualifiedName {
self.name
}
}
#[derive(Clone, Debug)]
pub enum ConstantValue {
Integer(BigInt),
String(String),
Sequence(Vec<ConstantValue>),
Case(String, Vec<ConstantValue>),
Record(ConstantValueRecord),
Constant(QualifiedName),
}
#[derive(Clone, Debug)]
pub struct ConstantValueRecord {
field_values: HashMap<String, ConstantValue>,
}
impl ConstantValueRecord {
pub fn field_values<'a>(&'a self) -> &'a HashMap<String, ConstantValue> {
&self.field_values
}
pub fn into_field_values(self) -> HashMap<String, ConstantValue> {
self.field_values
}
}
pub struct ConstantValueRecordBuilder {
field_names: HashSet<String>,
record: ConstantValueRecord,
}
impl ConstantValueRecordBuilder {
pub fn new() -> Self {
ConstantValueRecordBuilder {
field_names: HashSet::new(),
record: ConstantValueRecord {
field_values: HashMap::new(),
},
}
}
pub fn add_field(&mut self, name: String, value: ConstantValue) -> Result<(), ModelError> {
if self.field_names.insert(name.to_ascii_uppercase()) {
self.record.field_values.insert(name, value);
Ok(())
}
else {
Err(ModelError::DuplicateFieldValue(name))
}
}
pub fn build(self) -> ConstantValueRecord {
self.record
}
}
pub struct ConstantVersionInfo<'a> {
pub version: BigUint,
pub value: Option<&'a ConstantValue>,
dummy: PhantomData<()>,
}
pub struct Constant {
imports: HashMap<String, ScopeLookup>,
value_type: Type,
versions: HashMap<BigUint, ConstantValue>,
}
pub struct ConstantBuilder {
name: QualifiedName,
constant: Constant,
}
impl ConstantBuilder {
pub fn new(name: QualifiedName, value_type: Type, imports: HashMap<String, ScopeLookup>) -> Self {
ConstantBuilder {
name: name,
constant: Constant {
imports: imports,
value_type: value_type,
versions: HashMap::new(),
},
}
}
pub fn add_version(&mut self, version: BigUint, value: ConstantValue) -> Result<(), ModelError> {
if self.constant.versions.contains_key(&version) {
Err(ModelError::DuplicateVersion(self.name.clone(), version.clone()))
}
else {
self.constant.versions.insert(version, value);
Ok(())
}
}
}
impl <'a> Named<'a, Constant> {
pub fn value_type(self) -> &'a Type {
&self.value.value_type
}
pub fn referenced_types(self) -> ReferencedTypeIterator<'a> {
ReferencedTypeIterator::from_type(&self.value.value_type)
}
pub fn versions(self) -> ConstantVersionIterator<'a> {
ConstantVersionIterator {
constant: self,
version: BigUint::one(),
has_prev_version: false,
max_version: self.model.metadata.latest_version.clone(),
}
}
pub fn scope(self) -> Scope<'a> {
Scope {
model: self.model,
current_pkg: Some(&self.name.package),
imports: Some(&self.value.imports),
type_params: None,
}
}
}
#[derive(Debug)]
pub struct FieldInfo {
pub field_type: Type,
}
#[derive(Debug)]
pub struct TypeVersionDefinition {
fields: Vec<(String, FieldInfo)>,
}
impl TypeVersionDefinition {
pub fn fields(&self) -> &Vec<(String, FieldInfo)> {
&self.fields
}
}
pub struct TypeVersionDefinitionBuilder<'a> {
name: &'a QualifiedName,
version: BigUint,
field_names: HashSet<String>,
ver_type: &'a mut TypeVersionDefinition,
}
impl <'a> TypeVersionDefinitionBuilder<'a> {
pub fn add_field(&mut self, name: String, field: FieldInfo) -> Result<(), ModelError> {
if self.field_names.insert(name.to_ascii_uppercase()) {
self.ver_type.fields.push((name, field));
Ok(())
}
else {
Err(ModelError::DuplicateField(self.name.clone(), self.version.clone(), name))
}
}
}
#[derive(Debug)]
pub struct TypeVersionInfo<'a> {
pub version: BigUint,
pub explicit_version: bool,
pub ver_type: &'a TypeVersionDefinition,
dummy: PhantomData<()>,
}
impl <'a> Clone for TypeVersionInfo<'a> {
fn clone(&self) -> Self {
TypeVersionInfo {
version: self.version.clone(),
explicit_version: self.explicit_version,
ver_type: self.ver_type,
dummy: PhantomData {}
}
}
}
#[derive(Debug)]
pub struct VersionedTypeDefinitionData {
imports: HashMap<String, ScopeLookup>,
type_params: Vec<String>,
versions: HashMap<BigUint, TypeVersionDefinition>,
is_final: bool,
}
pub struct VersionedTypeDefinitionBuilder {
name: QualifiedName,
t: VersionedTypeDefinitionData,
}
impl VersionedTypeDefinitionBuilder {
pub fn new(name: QualifiedName, type_params: Vec<String>, is_final: bool, imports: HashMap<String, ScopeLookup>) -> Self {
VersionedTypeDefinitionBuilder {
name: name,
t: VersionedTypeDefinitionData {
imports: imports,
type_params: type_params,
is_final: is_final,
versions: HashMap::new(),
},
}
}
pub fn add_version<'a>(&'a mut self, version: BigUint) -> Result<TypeVersionDefinitionBuilder<'a>, ModelError> {
match self.t.versions.entry(version.clone()) {
std::collections::hash_map::Entry::Occupied(_) => Err(ModelError::DuplicateVersion(self.name.clone(), version)),
std::collections::hash_map::Entry::Vacant(entry) => {
let ver_type = entry.insert(TypeVersionDefinition {
fields: Vec::new(),
});
Ok(TypeVersionDefinitionBuilder {
name: &self.name,
version: version,
field_names: HashSet::new(),
ver_type: ver_type,
})
}
}
}
}
impl <'a> Named<'a, VersionedTypeDefinitionData> {
pub fn is_final(&self) -> bool {
self.value.is_final
}
pub fn versioned(self, version: &BigUint) -> Option<TypeVersionInfo<'a>> {
self.value.versions.iter()
.filter(|(ver, _)| ver <= &version)
.max_by_key(|(ver, _)| ver.clone())
.map(|(actual_ver, ver_type)| {
let ver =
if self.value.is_final && !self.value.versions.keys().any(|other_ver| other_ver > actual_ver) {
actual_ver.clone()
}
else {
version.clone()
};
TypeVersionInfo {
version: ver,
explicit_version: version == actual_ver,
ver_type: ver_type,
dummy: PhantomData {},
}
})
}
pub fn last_explicit_version(self) -> Option<&'a BigUint> {
self.value.versions.keys().max()
}
pub fn referenced_types(self) -> ReferencedTypeIterator<'a> {
ReferencedTypeIterator::from_versions(&self.value.versions)
}
pub fn versions(self) -> TypeVersionIterator<'a> {
TypeVersionIterator {
type_def: self,
version: BigUint::one(),
max_version:
if self.value.is_final {
self.last_explicit_version().map(|ver| ver.clone()).unwrap_or(BigUint::zero())
}
else {
self.model.metadata.latest_version.clone()
},
last_seen_version: None,
}
}
pub fn scope(self) -> Scope<'a> {
Scope {
model: self.model,
current_pkg: Some(&self.name.package),
imports: Some(&self.value.imports),
type_params: Some(&self.value.type_params),
}
}
pub fn type_params(self) -> &'a Vec<String> {
&self.value.type_params
}
}
#[derive(Debug)]
pub struct ExternTypeDefinitionData {
imports: HashMap<String, ScopeLookup>,
type_params: Vec<String>,
literals: Vec<ExternLiteralSpecifier>,
}
pub struct ExternTypeDefinitionBuilder {
name: QualifiedName,
has_integer: bool,
has_string: bool,
has_sequence: bool,
cases: HashSet<String>,
has_record: bool,
t: ExternTypeDefinitionData,
}
pub struct ExternLiteralRecordBuilder<'a> {
name: &'a QualifiedName,
field_names: HashSet<String>,
fields: &'a mut Vec<(String, FieldInfo)>,
}
impl ExternTypeDefinitionBuilder {
pub fn new(name: QualifiedName, type_params: Vec<String>, imports: HashMap<String, ScopeLookup>) -> Self {
ExternTypeDefinitionBuilder {
name: name,
has_integer: false,
has_string: false,
has_sequence: false,
cases: HashSet::new(),
has_record: false,
t: ExternTypeDefinitionData {
imports: imports,
type_params: type_params,
literals: Vec::new(),
},
}
}
pub fn add_integer_literal(&mut self, lower_type: ExternLiteralIntBound, lower: Option<BigInt>, upper_type: ExternLiteralIntBound, upper: Option<BigInt>) -> Result<(), ModelError> {
if self.has_integer {
Err(ModelError::DuplicateLiteralInteger(self.name.clone()))
}
else {
self.t.literals.push(ExternLiteralSpecifier::Integer(lower_type, lower, upper_type, upper));
self.has_integer = true;
Ok(())
}
}
pub fn add_string_literal(&mut self) -> Result<(), ModelError> {
if self.has_string {
Err(ModelError::DuplicateLiteralString(self.name.clone()))
}
else {
self.t.literals.push(ExternLiteralSpecifier::String);
self.has_string = true;
Ok(())
}
}
pub fn add_sequence_literal(&mut self, element_type: Type) -> Result<(), ModelError> {
if self.has_sequence {
Err(ModelError::DuplicateLiteralSequence(self.name.clone()))
}
else {
self.t.literals.push(ExternLiteralSpecifier::Sequence(element_type));
self.has_sequence = true;
Ok(())
}
}
pub fn add_case_literal(&mut self, case_name: String, params: Vec<Type>) -> Result<(), ModelError> {
if self.cases.insert(case_name.to_ascii_uppercase()) {
self.t.literals.push(ExternLiteralSpecifier::Case(case_name, params));
Ok(())
}
else {
Err(ModelError::DuplicateLiteralCase(self.name.clone(), case_name))
}
}
pub fn add_record_literal<'a>(&'a mut self) -> Result<ExternLiteralRecordBuilder<'a>, ModelError> {
if self.has_record {
Err(ModelError::DuplicateLiteralRecord(self.name.clone()))
}
else {
self.has_record = true;
self.t.literals.push(ExternLiteralSpecifier::Record(Vec::new()));
let fields = match self.t.literals.last_mut() {
Some(ExternLiteralSpecifier::Record(fields)) => fields,
_ => panic!("Last element should have been a record"),
};
Ok(ExternLiteralRecordBuilder {
name: &self.name,
field_names: HashSet::new(),
fields: fields,
})
}
}
}
impl <'a> ExternLiteralRecordBuilder<'a> {
pub fn add_field(&mut self, name: String, field: FieldInfo) -> Result<(), ModelError> {
if self.field_names.insert(name.to_ascii_uppercase()) {
self.fields.push((name, field));
Ok(())
}
else {
Err(ModelError::DuplicateLiteralRecordField(self.name.clone(), name))
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ExternLiteralIntBound {
Inclusive,
Exclusive,
}
#[derive(Debug)]
pub enum ExternLiteralSpecifier {
Integer(ExternLiteralIntBound, Option<BigInt>, ExternLiteralIntBound, Option<BigInt>),
String,
Sequence(Type),
Case(String, Vec<Type>),
Record(Vec<(String, FieldInfo)>),
}
impl <'a> Named<'a, ExternTypeDefinitionData> {
pub fn literals(self) -> &'a Vec<ExternLiteralSpecifier> {
&self.value.literals
}
pub fn scope(self) -> Scope<'a> {
Scope {
model: self.model,
current_pkg: Some(&self.name.package),
imports: Some(&self.value.imports),
type_params: Some(&self.value.type_params),
}
}
pub fn type_params(self) -> &'a Vec<String> {
&self.value.type_params
}
}
pub enum TypeDefinition {
StructType(VersionedTypeDefinitionData),
EnumType(VersionedTypeDefinitionData),
ExternType(ExternTypeDefinitionData),
}
#[derive(Copy, Clone)]
pub enum NamedTypeDefinition<'a> {
StructType(Named<'a, VersionedTypeDefinitionData>),
EnumType(Named<'a, VersionedTypeDefinitionData>),
ExternType(Named<'a, ExternTypeDefinitionData>),
}
impl <'a> NamedTypeDefinition<'a> {
pub fn name(&self) -> &'a QualifiedName {
match self {
NamedTypeDefinition::StructType(t) => t.name,
NamedTypeDefinition::EnumType(t) => t.name,
NamedTypeDefinition::ExternType(t) => t.name,
}
}
pub fn type_params(&self) -> &'a Vec<String> {
match self {
NamedTypeDefinition::StructType(t) => &t.value.type_params,
NamedTypeDefinition::EnumType(t) => &t.value.type_params,
NamedTypeDefinition::ExternType(t) => &t.value.type_params,
}
}
pub fn arity(&self) -> usize {
self.type_params().len()
}
pub fn has_version(self, version: &BigUint) -> bool {
match self {
NamedTypeDefinition::StructType(t) => t.versioned(version).is_some(),
NamedTypeDefinition::EnumType(t) => t.versioned(version).is_some(),
NamedTypeDefinition::ExternType(_) => true,
}
}
}
pub struct VerilizationMetadata {
pub latest_version: BigUint,
}
pub struct Verilization {
metadata: VerilizationMetadata,
constants: HashMap<QualifiedName, Constant>,
type_definitions: HashMap<QualifiedName, TypeDefinition>,
names: HashSet<QualifiedName>,
}
#[derive(Clone, Debug)]
pub enum ScopeLookup {
NamedType(QualifiedName),
TypeParameter(String),
}
pub struct Scope<'a> {
model: &'a Verilization,
current_pkg: Option<&'a PackageName>,
imports: Option<&'a HashMap<String, ScopeLookup>>,
type_params: Option<&'a Vec<String>>,
}
impl <'a> Scope<'a> {
pub fn empty(model: &'a Verilization) -> Self {
Scope {
model: model,
current_pkg: None,
imports: None,
type_params: None,
}
}
pub fn lookup(&self, mut name: QualifiedName) -> ScopeLookup {
if name.package.package.is_empty() {
if let Some(type_params) = self.type_params {
if type_params.contains(&name.name) {
return ScopeLookup::TypeParameter(name.name);
}
}
if let Some(import) = self.imports.and_then(|imports| imports.get(&name.name)) {
return import.clone();
}
if let Some(current_pkg) = self.current_pkg {
let current_pkg_name = QualifiedName {
package: current_pkg.clone(),
name: name.name,
};
if self.model.has_type(¤t_pkg_name) {
return ScopeLookup::NamedType(current_pkg_name);
}
name.name = current_pkg_name.name;
}
}
ScopeLookup::NamedType(name)
}
pub fn type_params(&self) -> Vec<String> {
match self.type_params {
Some(params) => params.clone(),
None => Vec::new(),
}
}
}
fn make_name_uppercase(name: &mut QualifiedName) {
for part in &mut name.package.package {
part.make_ascii_uppercase();
}
name.name.make_ascii_uppercase();
}
impl Verilization {
pub fn new(metadata: VerilizationMetadata) -> Self {
Verilization {
metadata: metadata,
constants: HashMap::new(),
type_definitions: HashMap::new(),
names: HashSet::new(),
}
}
pub fn add_constant(&mut self, constant: ConstantBuilder) -> Result<(), ModelError> {
let mut case_name = constant.name.clone();
make_name_uppercase(&mut case_name);
if self.names.insert(case_name) {
self.constants.insert(constant.name, constant.constant);
Ok(())
}
else {
Err(ModelError::DuplicateConstant(constant.name))
}
}
pub fn add_struct_type(&mut self, type_def: VersionedTypeDefinitionBuilder) -> Result<(), ModelError> {
let mut case_name = type_def.name.clone();
make_name_uppercase(&mut case_name);
if self.names.insert(case_name) {
self.type_definitions.insert(type_def.name, TypeDefinition::StructType(type_def.t));
Ok(())
}
else {
Err(ModelError::DuplicateType(type_def.name))
}
}
pub fn add_enum_type(&mut self, type_def: VersionedTypeDefinitionBuilder) -> Result<(), ModelError> {
let mut case_name = type_def.name.clone();
make_name_uppercase(&mut case_name);
if self.names.insert(case_name) {
self.type_definitions.insert(type_def.name, TypeDefinition::EnumType(type_def.t));
Ok(())
}
else {
Err(ModelError::DuplicateType(type_def.name))
}
}
pub fn add_extern_type(&mut self, type_def: ExternTypeDefinitionBuilder) -> Result<(), ModelError> {
let mut case_name = type_def.name.clone();
make_name_uppercase(&mut case_name);
if self.names.insert(case_name) {
self.type_definitions.insert(type_def.name, TypeDefinition::ExternType(type_def.t));
Ok(())
}
else {
Err(ModelError::DuplicateType(type_def.name))
}
}
pub fn get_constant<'a>(&'a self, name: &QualifiedName) -> Option<Named<'a, Constant>> {
let (name, constant) = self.constants.get_key_value(name)?;
Some(Named::new(self, name, constant))
}
pub fn get_type<'a>(&'a self, name: &QualifiedName) -> Option<NamedTypeDefinition<'a>> {
let (name, t) = self.type_definitions.get_key_value(name)?;
Some(match t {
TypeDefinition::StructType(t) => NamedTypeDefinition::StructType(Named::new(self, name, t)),
TypeDefinition::EnumType(t) => NamedTypeDefinition::EnumType(Named::new(self, name, t)),
TypeDefinition::ExternType(t) => NamedTypeDefinition::ExternType(Named::new(self, name, t)),
})
}
pub fn has_type<'a>(&'a self, name: &QualifiedName) -> bool {
self.type_definitions.contains_key(name)
}
pub fn merge(&mut self, other: Verilization) -> Result<(), ModelError> {
if self.metadata.latest_version < other.metadata.latest_version {
self.metadata.latest_version = other.metadata.latest_version
}
other.constants.into_iter().try_for_each(|(name, constant)| self.add_constant(ConstantBuilder { name: name, constant: constant }))?;
other.type_definitions.into_iter().try_for_each(|(name, t)| match t {
TypeDefinition::StructType(type_def) => self.add_struct_type(VersionedTypeDefinitionBuilder { name: name, t: type_def }),
TypeDefinition::EnumType(type_def) => self.add_enum_type(VersionedTypeDefinitionBuilder { name: name, t: type_def }),
TypeDefinition::ExternType(type_def) => self.add_extern_type(ExternTypeDefinitionBuilder { name: name, t: type_def, has_integer: false, has_string: false, has_sequence: false, cases: HashSet::new(), has_record: false, }),
})?;
Ok(())
}
pub fn constants<'a>(&'a self) -> ConstantIterator<'a> {
ConstantIterator {
model: self,
iter: self.constants.iter(),
}
}
pub fn types<'a>(&'a self) -> TypeIterator<'a> {
TypeIterator {
model: self,
iter: self.type_definitions.iter(),
}
}
}
pub struct ConstantIterator<'a> {
model: &'a Verilization,
iter: std::collections::hash_map::Iter<'a, QualifiedName, Constant>,
}
impl <'a> Iterator for ConstantIterator<'a> {
type Item = Named<'a, Constant>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|(name, constant)| Named::new(self.model, name, constant))
}
}
pub struct ConstantVersionIterator<'a> {
constant: Named<'a, Constant>,
version: BigUint,
max_version: BigUint,
has_prev_version: bool,
}
impl <'a> Iterator for ConstantVersionIterator<'a> {
type Item = ConstantVersionInfo<'a>;
fn next(&mut self) -> Option<Self::Item> {
while self.version <= self.max_version {
let version = self.version.clone();
self.version += BigUint::one();
if let Some(ver_type) = self.constant.value.versions.get(&version) {
self.has_prev_version = true;
return Some(ConstantVersionInfo {
version: version,
value: Some(ver_type),
dummy: PhantomData {},
});
}
else if self.has_prev_version {
return Some(ConstantVersionInfo {
version: version,
value: None,
dummy: PhantomData {},
});
}
}
None
}
}
pub struct TypeIterator<'a> {
model: &'a Verilization,
iter: std::collections::hash_map::Iter<'a, QualifiedName, TypeDefinition>,
}
impl <'a> Iterator for TypeIterator<'a> {
type Item = NamedTypeDefinition<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|(name, t)| match t {
TypeDefinition::StructType(t) => NamedTypeDefinition::StructType(Named::new(self.model, name, t)),
TypeDefinition::EnumType(t) => NamedTypeDefinition::EnumType(Named::new(self.model, name, t)),
TypeDefinition::ExternType(t) => NamedTypeDefinition::ExternType(Named::new(self.model, name, t)),
})
}
}
pub struct TypeVersionIterator<'a> {
type_def: Named<'a, VersionedTypeDefinitionData>,
version: BigUint,
max_version: BigUint,
last_seen_version: Option<&'a TypeVersionDefinition>,
}
impl <'a> Iterator for TypeVersionIterator<'a> {
type Item = TypeVersionInfo<'a>;
fn next(&mut self) -> Option<Self::Item> {
while self.version <= self.max_version {
let version = self.version.clone();
self.version += BigUint::one();
if let Some(ver_type) = self.type_def.value.versions.get(&version) {
self.last_seen_version = Some(ver_type);
return Some(TypeVersionInfo {
version: version,
explicit_version: true,
ver_type: ver_type,
dummy: PhantomData {},
});
}
else if let Some(ver_type) = self.last_seen_version {
return Some(TypeVersionInfo {
version: version,
explicit_version: false,
ver_type: ver_type,
dummy: PhantomData {},
});
}
}
None
}
}
pub struct ReferencedTypeIterator<'a> {
seen_types: HashSet<&'a QualifiedName>,
ver_iter: std::collections::hash_map::Values<'a, BigUint, TypeVersionDefinition>,
field_iter: std::slice::Iter<'a, (String, FieldInfo)>,
arg_iters: Vec<std::slice::Iter<'a, Type>>,
}
lazy_static! {
static ref REF_TYPE_ITER_EMPTY_VER_MAP: HashMap<BigUint, TypeVersionDefinition> = HashMap::new();
}
const REF_TYPE_ITER_EMPTY_FIELD_SLICE: &[(String, FieldInfo)] = &[];
impl <'a> Iterator for ReferencedTypeIterator<'a> {
type Item = &'a QualifiedName;
fn next(&mut self) -> Option<Self::Item> {
loop {
while let Some(arg_iter) = self.arg_iters.last_mut() {
if let Some(arg) = arg_iter.next() {
self.arg_iters.push(arg.args.iter());
if self.seen_types.insert(&arg.name) {
return Some(&arg.name);
}
}
else {
self.arg_iters.pop();
}
}
if let Some((_, field)) = self.field_iter.next() {
self.arg_iters.push(std::slice::from_ref(&field.field_type).iter());
}
else if let Some(ver_type) = self.ver_iter.next() {
self.field_iter = ver_type.fields.iter();
}
else {
return None;
}
}
}
}
impl <'a> ReferencedTypeIterator<'a> {
fn from_versions(versions: &'a HashMap<BigUint, TypeVersionDefinition>) -> ReferencedTypeIterator<'a> {
ReferencedTypeIterator {
seen_types: HashSet::new(),
ver_iter: versions.values(),
field_iter: REF_TYPE_ITER_EMPTY_FIELD_SLICE.iter(),
arg_iters: Vec::new(),
}
}
fn from_type(t: &'a Type) -> ReferencedTypeIterator<'a> {
ReferencedTypeIterator {
seen_types: HashSet::new(),
ver_iter: REF_TYPE_ITER_EMPTY_VER_MAP.values(),
field_iter: REF_TYPE_ITER_EMPTY_FIELD_SLICE.iter(),
arg_iters: vec!(std::slice::from_ref(t).iter()),
}
}
}