blob: c1a412e0f7e07808c2ef8072022e19eab16ef13c [file] [log] [blame]
// Copyright 2022 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
// Allows presubmit to fail on warnings.
#![cfg_attr(feature = "strict", deny(warnings))]
#![warn(clippy::pedantic)]
use std::path::{Path, PathBuf};
pub mod platform;
pub mod project;
pub mod registry;
pub mod target;
mod digest;
mod download;
mod executor;
mod util;
#[cfg(test)]
pub(crate) mod fake;
#[cfg(test)]
pub(crate) mod test_util;
#[doc(inline)]
pub use target::Target;
#[doc(inline)]
pub use project::Project;
#[cfg(feature = "python")]
mod py;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(thiserror::Error, Debug)]
#[non_exhaustive]
pub enum Error {
#[error("I/O error")]
Io(#[from] std::io::Error),
/// Error occurred when attempting to modify a file.
#[error("{0}: {1}")]
File(PathBuf, std::io::Error),
#[error("failed to serialize data: {0}")]
Serialization(String),
#[error("project not found")]
ProjectNotFound,
#[error(r#""{0}" is not a valid name"#)]
InvalidName(String),
#[error("invalid path")]
InvalidPath,
// TODO(frolv): This is a placeholder error returned by some functions until
// a real error handling model is figured out.
#[error("placeholder error, please bug the qg team")]
GenericErrorPlaceholder,
// TODO(frolv): This is a placeholder error returned by some functions until
// a real error handling model is figured out.
#[error("placeholder error with string, please bug the qg team: {0}")]
StringErrorPlaceholder(String),
}
impl Error {
pub(crate) fn file(path: impl AsRef<Path>) -> impl FnOnce(std::io::Error) -> Self {
move |e| Self::File(path.as_ref().to_path_buf(), e)
}
}
impl From<toml::ser::Error> for Error {
fn from(e: toml::ser::Error) -> Self {
Self::Serialization(e.to_string())
}
}
impl From<toml::de::Error> for Error {
fn from(e: toml::de::Error) -> Self {
Self::Serialization(e.to_string())
}
}
#[must_use]
pub fn name() -> &'static str {
"qg"
}
#[cfg(feature = "python")]
/// Executes some python code.
///
/// # Panics
/// Panics if `py_demo` can not convert its internal `TestStruct` to a Python object.
pub fn py_demo(code: &str) {
use py::Py;
use serde::Serialize;
#[derive(Debug, Serialize)]
pub struct TestStruct {
i: i32,
s: String,
}
let mut py = Py::new();
let py_result = py.run(
// Scope initialization function.
|vm, scope| {
// Add a `rust_print` function to the scope before running the code.
let object = TestStruct {
i: 1,
s: "Hello QG!".into(),
};
scope
.globals
.set_item("data", py::to_python_object(vm, &object).unwrap(), vm)?;
scope.globals.set_item(
"rust_print",
vm.ctx
.new_function("rust_print", |s: String| println!("[R] {s}"))
.into(),
vm,
)?;
Ok(())
},
code,
);
if let Err(e) = py_result {
// Placeholder until qg has an error type
println!("py_demo error: {e:?}");
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
assert_eq!(name(), "qg");
}
}