ab_contracts_tooling/
target_specification.rs1use anyhow::Context;
4use dirs::cache_dir;
5use std::fs::{File, create_dir_all};
6use std::io::{Read, Seek, Write};
7use std::path::{Path, PathBuf};
8
9const TARGET_SPECIFICATION: &str = include_str!("riscv64em-unknown-none-abundance.json");
10
11#[derive(Debug)]
13pub struct TargetSpecification {
14 path: PathBuf,
15 _file: File,
16}
17
18impl TargetSpecification {
19 pub fn create(base_directory: &Path) -> anyhow::Result<Self> {
23 let path = base_directory.join("riscv64em-unknown-none-abundance.json");
24 let mut file = File::options()
25 .read(true)
26 .write(true)
27 .create(true)
28 .truncate(false)
29 .open(&path)
30 .context("Failed to open target specification file")?;
31
32 loop {
34 file.lock_shared()
35 .context("Failed to lock target specification file")?;
36
37 let mut actual_target_specification = String::with_capacity(TARGET_SPECIFICATION.len());
38 file.seek(std::io::SeekFrom::Start(0))
39 .context("Failed to seek to start of target specification file")?;
40 file.read_to_string(&mut actual_target_specification)
41 .context("Failed to read target specification file")?;
42
43 if actual_target_specification == TARGET_SPECIFICATION {
44 break;
45 }
46
47 file.unlock()
48 .context("Failed to unlock target specification file")?;
49 file.lock()
50 .context("Failed to lock target specification file")?;
51 file.set_len(0)
52 .context("Failed to truncate target specification file")?;
53 file.seek(std::io::SeekFrom::Start(0))
54 .context("Failed to seek to start of target specification file")?;
55 file.write_all(TARGET_SPECIFICATION.as_bytes())
56 .context("Failed to write target specification file")?;
57 file.sync_all()
58 .context("Failed to sync target specification file")?;
59 file.unlock()
60 .context("Failed to unlock target specification file")?;
61 }
62
63 Ok(Self { path, _file: file })
64 }
65
66 pub fn default_base_dir() -> anyhow::Result<PathBuf> {
69 let app_dir = cache_dir()
70 .context("Failed to get cache directory")?
71 .join("ab-contracts");
72 create_dir_all(&app_dir)
73 .with_context(|| format!("Failed to create cache directory {}", app_dir.display()))?;
74
75 Ok(app_dir)
76 }
77
78 pub fn path(&self) -> &Path {
80 &self.path
81 }
82}