snarkvm_debug/file/
manifest.rs

1// Copyright (C) 2019-2023 Aleo Systems Inc.
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7// http://www.apache.org/licenses/LICENSE-2.0
8
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::{
16    prelude::{Network, ProgramID},
17    synthesizer::Program,
18};
19
20use anyhow::{anyhow, ensure, Result};
21use core::str::FromStr;
22use std::{
23    fs::{self, File},
24    io::Write,
25    path::{Path, PathBuf},
26};
27
28const MANIFEST_FILE_NAME: &str = "program.json";
29
30pub struct Manifest<N: Network> {
31    /// The file path.
32    path: PathBuf,
33    /// The program ID.
34    program_id: ProgramID<N>,
35}
36
37impl<N: Network> Manifest<N> {
38    /// Creates a new manifest file with the given directory path and program ID.
39    pub fn create(directory: &Path, id: &ProgramID<N>) -> Result<Self> {
40        // Ensure the directory path exists.
41        ensure!(directory.exists(), "The program directory does not exist: '{}'", directory.display());
42        // Ensure the program name is valid.
43        ensure!(!Program::is_reserved_keyword(id.name()), "Program name is invalid (reserved): {id}");
44
45        // Construct the initial program manifest string.
46        let manifest_string = format!(
47            r#"{{
48    "program": "{id}",
49    "version": "0.0.0",
50    "description": "",
51    "license": "MIT"
52}}
53"#
54        );
55
56        // Construct the file path.
57        let path = directory.join(MANIFEST_FILE_NAME);
58        // Ensure the file path does not already exist.
59        ensure!(!path.exists(), "Manifest file already exists: '{}'", path.display());
60
61        // Write the file.
62        File::create(&path)?.write_all(manifest_string.as_bytes())?;
63
64        // Return the manifest file.
65        Ok(Self { path, program_id: *id })
66    }
67
68    /// Opens the manifest file for reading.
69    pub fn open(directory: &Path) -> Result<Self> {
70        // Ensure the directory path exists.
71        ensure!(directory.exists(), "The program directory does not exist: '{}'", directory.display());
72
73        // Construct the file path.
74        let path = directory.join(MANIFEST_FILE_NAME);
75        // Ensure the file path exists.
76        ensure!(path.exists(), "Manifest file is missing: '{}'", path.display());
77
78        // Read the file to a string.
79        let manifest_string = fs::read_to_string(&path)?;
80        let json: serde_json::Value = serde_json::from_str(&manifest_string)?;
81
82        // Retrieve the program ID.
83        let id_string = json["program"].as_str().ok_or_else(|| anyhow!("Program ID not found."))?;
84        let id = ProgramID::from_str(id_string)?;
85        // Ensure the program name is valid.
86        ensure!(!Program::is_reserved_keyword(id.name()), "Program name is invalid (reserved): {id}");
87
88        // Return the manifest file.
89        Ok(Self { path, program_id: id })
90    }
91
92    /// Returns `true` if the manifest file exists at the given path.
93    pub fn exists_at(directory: &Path) -> bool {
94        // Construct the file path.
95        let path = directory.join(MANIFEST_FILE_NAME);
96        // Return the result.
97        path.is_file() && path.exists()
98    }
99
100    /// Returns the manifest file name.
101    pub const fn file_name() -> &'static str {
102        MANIFEST_FILE_NAME
103    }
104
105    /// Returns the file path.
106    pub const fn path(&self) -> &PathBuf {
107        &self.path
108    }
109
110    /// Returns the program ID.
111    pub const fn program_id(&self) -> &ProgramID<N> {
112        &self.program_id
113    }
114}