prusti_specs/specifications/
common.rs1use std::{
7 convert::TryFrom,
8 fmt::{Debug, Display},
9};
10use uuid::Uuid;
11
12#[derive(Clone, Copy, Debug, PartialEq, Eq)]
13pub enum SpecType {
15 Precondition,
17 Postcondition,
19 Invariant,
21 Predicate,
23 StructInvariant,
25}
26
27#[derive(Debug)]
28pub enum TryFromStringError {
30 UnknownSpecificationType,
33}
34
35impl<'a> TryFrom<&'a str> for SpecType {
36 type Error = TryFromStringError;
37
38 fn try_from(typ: &str) -> Result<SpecType, TryFromStringError> {
39 match typ {
40 "requires" => Ok(SpecType::Precondition),
41 "ensures" => Ok(SpecType::Postcondition),
42 "invariant" => Ok(SpecType::Invariant),
43 "predicate" => Ok(SpecType::Predicate),
44 _ => Err(TryFromStringError::UnknownSpecificationType),
45 }
46 }
47}
48
49#[derive(Debug, Default, PartialEq, Eq, Hash, Clone, Copy, PartialOrd, Ord)]
50pub struct SpecificationId(Uuid);
53
54#[derive(Debug, Clone, Copy)]
56pub enum SpecIdRef {
57 Precondition(SpecificationId),
58 Postcondition(SpecificationId),
59 Purity(SpecificationId),
60 Pledge {
61 lhs: Option<SpecificationId>,
62 rhs: SpecificationId,
63 },
64 Predicate(SpecificationId),
65 Terminates(SpecificationId),
66}
67
68impl Display for SpecificationId {
69 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70 write!(
71 f,
72 "{}",
73 self.0.simple().encode_lower(&mut Uuid::encode_buffer()),
74 )
75 }
76}
77
78impl std::convert::TryFrom<String> for SpecificationId {
79 type Error = uuid::Error;
80 fn try_from(value: String) -> Result<Self, Self::Error> {
81 Uuid::parse_str(&value).map(Self)
82 }
83}
84
85impl SpecificationId {
86 pub fn dummy() -> Self {
87 Self(Uuid::nil())
88 }
89}
90
91pub(crate) struct SpecificationIdGenerator {}
92
93impl SpecificationIdGenerator {
94 pub(crate) fn new() -> Self {
95 Self {}
96 }
97 pub(crate) fn generate(&mut self) -> SpecificationId {
98 SpecificationId(Uuid::new_v4())
99 }
100}
101
102pub(crate) fn generate_struct_name(item: &syn::ItemImpl) -> String {
103 let uuid = Uuid::new_v4().simple();
104 let name_ty = generate_name_for_type(&item.self_ty).unwrap_or_default();
105 format!("PrustiStruct{name_ty}_{uuid}")
106}
107
108pub(crate) fn generate_struct_name_for_trait(item: &syn::ItemTrait) -> String {
109 let uuid = Uuid::new_v4().simple();
110 format!("PrustiTrait{}_{}", item.ident, uuid)
111}
112
113fn generate_name_for_type(ty: &syn::Type) -> Option<String> {
114 match ty {
115 syn::Type::Path(ty_path) => Some(String::from_iter(
116 ty_path
117 .path
118 .segments
119 .iter()
120 .map(|seg| seg.ident.to_string()),
121 )),
122 syn::Type::Slice(ty_slice) => {
123 let ty = &*ty_slice.elem;
124 Some(format!("Slice{}", generate_name_for_type(ty)?.as_str()))
125 }
126 _ => None,
127 }
128}