1use anyhow::{bail, Result};
4use std::path::Path;
5
6use crate::link::Link;
7use crate::link_storage::LinkStorage;
8
9pub trait PinnedTypesAccess {
10 fn pinned_types(&mut self, count: usize) -> Result<Vec<u32>>;
11
12 fn deconstruct_pinned_types(&mut self) -> Result<(u32, u32, u32)> {
13 let pinned_types = self.pinned_types(3)?;
14 Ok((pinned_types[0], pinned_types[1], pinned_types[2]))
15 }
16}
17
18pub struct PinnedTypes<'a> {
20 links: &'a mut LinkStorage,
21 current: u32,
22 initial_source: u32,
23}
24
25impl<'a> PinnedTypes<'a> {
26 pub fn new(links: &'a mut LinkStorage) -> Self {
27 Self {
28 links,
29 current: 1,
30 initial_source: 1,
31 }
32 }
33
34 pub fn next_type(&mut self) -> Result<u32> {
35 let address = self.current;
36 if let Some(link) = self.links.get(address) {
37 if link.index != address || link.source != self.initial_source || link.target != address
38 {
39 bail!(
40 "Unexpected link found at address {address}. Expected: ({address}: {} {address}), Found: ({}: {} {}).",
41 self.initial_source,
42 link.index,
43 link.source,
44 link.target
45 );
46 }
47 } else {
48 let created = self.links.get_or_create(self.initial_source, address);
49 if created != address {
50 bail!(
51 "Pinned type address {address} could not be created deterministically; got {created}."
52 );
53 }
54 }
55
56 self.current += 1;
57 Ok(address)
58 }
59
60 pub fn take_types(&mut self, count: usize) -> Result<Vec<u32>> {
61 (0..count).map(|_| self.next_type()).collect()
62 }
63
64 pub fn deconstruct(&mut self) -> Result<(u32, u32, u32)> {
65 let pinned_types = self.take_types(3)?;
66 Ok((pinned_types[0], pinned_types[1], pinned_types[2]))
67 }
68}
69
70pub struct PinnedTypesDecorator {
72 links: LinkStorage,
73}
74
75impl PinnedTypesDecorator {
76 pub fn new<P>(database_filename: P, trace: bool) -> Result<Self>
77 where
78 P: AsRef<Path>,
79 {
80 let database_path = database_filename.as_ref().to_string_lossy().into_owned();
81 let links = LinkStorage::new(&database_path, trace)?;
82 Ok(Self::from_link_storage(links))
83 }
84
85 pub fn from_link_storage(links: LinkStorage) -> Self {
86 Self { links }
87 }
88
89 pub fn links(&self) -> &LinkStorage {
90 &self.links
91 }
92
93 pub fn links_mut(&mut self) -> &mut LinkStorage {
94 &mut self.links
95 }
96
97 pub fn into_link_storage(self) -> LinkStorage {
98 self.links
99 }
100
101 pub fn save(&self) -> Result<()> {
102 self.links.save()
103 }
104
105 pub fn create(&mut self, source: u32, target: u32) -> u32 {
106 self.links.create(source, target)
107 }
108
109 pub fn ensure_created(&mut self, id: u32) -> u32 {
110 self.links.ensure_created(id)
111 }
112
113 pub fn get(&self, id: u32) -> Option<&Link> {
114 self.links.get(id)
115 }
116
117 pub fn exists(&self, id: u32) -> bool {
118 self.links.exists(id)
119 }
120
121 pub fn update(&mut self, id: u32, source: u32, target: u32) -> Result<Link> {
122 self.links.update(id, source, target)
123 }
124
125 pub fn delete(&mut self, id: u32) -> Result<Link> {
126 self.links.delete(id)
127 }
128
129 pub fn all(&self) -> Vec<&Link> {
130 self.links.all()
131 }
132
133 pub fn query(
134 &self,
135 index: Option<u32>,
136 source: Option<u32>,
137 target: Option<u32>,
138 ) -> Vec<&Link> {
139 self.links.query(index, source, target)
140 }
141
142 pub fn search(&self, source: u32, target: u32) -> Option<u32> {
143 self.links.search(source, target)
144 }
145
146 pub fn get_or_create(&mut self, source: u32, target: u32) -> u32 {
147 self.links.get_or_create(source, target)
148 }
149}
150
151impl PinnedTypesAccess for PinnedTypesDecorator {
152 fn pinned_types(&mut self, count: usize) -> Result<Vec<u32>> {
153 PinnedTypes::new(&mut self.links).take_types(count)
154 }
155}