use std::{borrow::Cow, collections::HashMap, convert::TryFrom, iter::FromIterator, path::Path};
pub const HEADER_V3: &[u8] = b"pyembed\x03";
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ResourceFlavor {
None = 0x00,
Module = 0x01,
BuiltinExtensionModule = 0x02,
FrozenModule = 0x03,
Extension = 0x04,
SharedLibrary = 0x05,
}
impl Default for ResourceFlavor {
fn default() -> Self {
ResourceFlavor::None
}
}
impl Into<u8> for ResourceFlavor {
fn into(self) -> u8 {
match self {
ResourceFlavor::None => 0x00,
ResourceFlavor::Module => 0x01,
ResourceFlavor::BuiltinExtensionModule => 0x02,
ResourceFlavor::FrozenModule => 0x03,
ResourceFlavor::Extension => 0x04,
ResourceFlavor::SharedLibrary => 0x05,
}
}
}
impl TryFrom<u8> for ResourceFlavor {
type Error = &'static str;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0x00 => Ok(ResourceFlavor::None),
0x01 => Ok(ResourceFlavor::Module),
0x02 => Ok(ResourceFlavor::BuiltinExtensionModule),
0x03 => Ok(ResourceFlavor::FrozenModule),
0x04 => Ok(ResourceFlavor::Extension),
0x05 => Ok(ResourceFlavor::SharedLibrary),
_ => Err("unrecognized resource flavor"),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum BlobInteriorPadding {
None = 0x01,
Null = 0x02,
}
impl Into<u8> for &BlobInteriorPadding {
fn into(self) -> u8 {
match self {
BlobInteriorPadding::None => 0x01,
BlobInteriorPadding::Null => 0x02,
}
}
}
#[derive(Debug, PartialEq, PartialOrd)]
pub enum BlobSectionField {
EndOfIndex = 0x00,
StartOfEntry = 0x01,
EndOfEntry = 0xff,
ResourceFieldType = 0x03,
RawPayloadLength = 0x04,
InteriorPadding = 0x05,
}
impl Into<u8> for BlobSectionField {
fn into(self) -> u8 {
match self {
BlobSectionField::EndOfIndex => 0x00,
BlobSectionField::StartOfEntry => 0x01,
BlobSectionField::ResourceFieldType => 0x02,
BlobSectionField::RawPayloadLength => 0x03,
BlobSectionField::InteriorPadding => 0x04,
BlobSectionField::EndOfEntry => 0xff,
}
}
}
impl TryFrom<u8> for BlobSectionField {
type Error = &'static str;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0x00 => Ok(BlobSectionField::EndOfIndex),
0x01 => Ok(BlobSectionField::StartOfEntry),
0x02 => Ok(BlobSectionField::ResourceFieldType),
0x03 => Ok(BlobSectionField::RawPayloadLength),
0x04 => Ok(BlobSectionField::InteriorPadding),
0xff => Ok(BlobSectionField::EndOfEntry),
_ => Err("invalid blob index field type"),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)]
pub enum ResourceField {
EndOfIndex = 0x00,
StartOfEntry = 0x01,
EndOfEntry = 0xff,
Flavor = 0x02,
ModuleName = 0x03,
IsPackage = 0x04,
IsNamespacePackage = 0x05,
InMemorySource = 0x06,
InMemoryBytecode = 0x07,
InMemoryBytecodeOpt1 = 0x08,
InMemoryBytecodeOpt2 = 0x09,
InMemoryExtensionModuleSharedLibrary = 0x0a,
InMemoryResourcesData = 0x0b,
InMemoryDistributionResource = 0x0c,
InMemorySharedLibrary = 0x0d,
SharedLibraryDependencyNames = 0x0e,
RelativeFilesystemModuleSource = 0x0f,
RelativeFilesystemModuleBytecode = 0x10,
RelativeFilesystemModuleBytecodeOpt1 = 0x11,
RelativeFilesystemModuleBytecodeOpt2 = 0x12,
RelativeFilesystemExtensionModuleSharedLibrary = 0x13,
RelativeFilesystemPackageResources = 0x14,
RelativeFilesystemDistributionResource = 0x15,
IsModule = 0x16,
IsBuiltinExtensionModule = 0x17,
IsFrozenModule = 0x18,
IsExtensionModule = 0x19,
IsSharedLibrary = 0x1a,
IsUtf8FilenameData = 0x1b,
FileExecutable = 0x1c,
FileDataEmbedded = 0x1d,
FileDataUtf8RelativePath = 0x1e,
}
impl Into<u8> for ResourceField {
fn into(self) -> u8 {
match self {
ResourceField::EndOfIndex => 0x00,
ResourceField::StartOfEntry => 0x01,
ResourceField::Flavor => 0x02,
ResourceField::ModuleName => 0x03,
ResourceField::IsPackage => 0x04,
ResourceField::IsNamespacePackage => 0x05,
ResourceField::InMemorySource => 0x06,
ResourceField::InMemoryBytecode => 0x07,
ResourceField::InMemoryBytecodeOpt1 => 0x08,
ResourceField::InMemoryBytecodeOpt2 => 0x09,
ResourceField::InMemoryExtensionModuleSharedLibrary => 0x0a,
ResourceField::InMemoryResourcesData => 0x0b,
ResourceField::InMemoryDistributionResource => 0x0c,
ResourceField::InMemorySharedLibrary => 0x0d,
ResourceField::SharedLibraryDependencyNames => 0x0e,
ResourceField::RelativeFilesystemModuleSource => 0x0f,
ResourceField::RelativeFilesystemModuleBytecode => 0x10,
ResourceField::RelativeFilesystemModuleBytecodeOpt1 => 0x11,
ResourceField::RelativeFilesystemModuleBytecodeOpt2 => 0x12,
ResourceField::RelativeFilesystemExtensionModuleSharedLibrary => 0x13,
ResourceField::RelativeFilesystemPackageResources => 0x14,
ResourceField::RelativeFilesystemDistributionResource => 0x15,
ResourceField::IsModule => 0x16,
ResourceField::IsBuiltinExtensionModule => 0x17,
ResourceField::IsFrozenModule => 0x18,
ResourceField::IsExtensionModule => 0x19,
ResourceField::IsSharedLibrary => 0x1a,
ResourceField::IsUtf8FilenameData => 0x1b,
ResourceField::FileExecutable => 0x1c,
ResourceField::FileDataEmbedded => 0x1d,
ResourceField::FileDataUtf8RelativePath => 0x1e,
ResourceField::EndOfEntry => 0xff,
}
}
}
impl TryFrom<u8> for ResourceField {
type Error = &'static str;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0x00 => Ok(ResourceField::EndOfIndex),
0x01 => Ok(ResourceField::StartOfEntry),
0x02 => Ok(ResourceField::Flavor),
0x03 => Ok(ResourceField::ModuleName),
0x04 => Ok(ResourceField::IsPackage),
0x05 => Ok(ResourceField::IsNamespacePackage),
0x06 => Ok(ResourceField::InMemorySource),
0x07 => Ok(ResourceField::InMemoryBytecode),
0x08 => Ok(ResourceField::InMemoryBytecodeOpt1),
0x09 => Ok(ResourceField::InMemoryBytecodeOpt2),
0x0a => Ok(ResourceField::InMemoryExtensionModuleSharedLibrary),
0x0b => Ok(ResourceField::InMemoryResourcesData),
0x0c => Ok(ResourceField::InMemoryDistributionResource),
0x0d => Ok(ResourceField::InMemorySharedLibrary),
0x0e => Ok(ResourceField::SharedLibraryDependencyNames),
0x0f => Ok(ResourceField::RelativeFilesystemModuleSource),
0x10 => Ok(ResourceField::RelativeFilesystemModuleBytecode),
0x11 => Ok(ResourceField::RelativeFilesystemModuleBytecodeOpt1),
0x12 => Ok(ResourceField::RelativeFilesystemModuleBytecodeOpt2),
0x13 => Ok(ResourceField::RelativeFilesystemExtensionModuleSharedLibrary),
0x14 => Ok(ResourceField::RelativeFilesystemPackageResources),
0x15 => Ok(ResourceField::RelativeFilesystemDistributionResource),
0x16 => Ok(ResourceField::IsModule),
0x17 => Ok(ResourceField::IsBuiltinExtensionModule),
0x18 => Ok(ResourceField::IsFrozenModule),
0x19 => Ok(ResourceField::IsExtensionModule),
0x1a => Ok(ResourceField::IsSharedLibrary),
0x1b => Ok(ResourceField::IsUtf8FilenameData),
0x1c => Ok(ResourceField::FileExecutable),
0x1d => Ok(ResourceField::FileDataEmbedded),
0x1e => Ok(ResourceField::FileDataUtf8RelativePath),
0xff => Ok(ResourceField::EndOfEntry),
_ => Err("invalid field type"),
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Resource<'a, X: 'a>
where
[X]: ToOwned<Owned = Vec<X>>,
{
pub flavor: ResourceFlavor,
pub name: Cow<'a, str>,
pub is_module: bool,
pub is_builtin_extension_module: bool,
pub is_frozen_module: bool,
pub is_extension_module: bool,
pub is_shared_library: bool,
pub is_utf8_filename_data: bool,
pub is_package: bool,
pub is_namespace_package: bool,
pub in_memory_source: Option<Cow<'a, [X]>>,
pub in_memory_bytecode: Option<Cow<'a, [X]>>,
pub in_memory_bytecode_opt1: Option<Cow<'a, [X]>>,
pub in_memory_bytecode_opt2: Option<Cow<'a, [X]>>,
pub in_memory_extension_module_shared_library: Option<Cow<'a, [X]>>,
pub in_memory_package_resources: Option<HashMap<Cow<'a, str>, Cow<'a, [X]>>>,
pub in_memory_distribution_resources: Option<HashMap<Cow<'a, str>, Cow<'a, [X]>>>,
pub in_memory_shared_library: Option<Cow<'a, [X]>>,
pub shared_library_dependency_names: Option<Vec<Cow<'a, str>>>,
pub relative_path_module_source: Option<Cow<'a, Path>>,
pub relative_path_module_bytecode: Option<Cow<'a, Path>>,
pub relative_path_module_bytecode_opt1: Option<Cow<'a, Path>>,
pub relative_path_module_bytecode_opt2: Option<Cow<'a, Path>>,
pub relative_path_extension_module_shared_library: Option<Cow<'a, Path>>,
pub relative_path_package_resources: Option<HashMap<Cow<'a, str>, Cow<'a, Path>>>,
pub relative_path_distribution_resources: Option<HashMap<Cow<'a, str>, Cow<'a, Path>>>,
pub file_executable: bool,
pub file_data_embedded: Option<Cow<'a, [X]>>,
pub file_data_utf8_relative_path: Option<Cow<'a, str>>,
}
impl<'a, X> Default for Resource<'a, X>
where
[X]: ToOwned<Owned = Vec<X>>,
{
fn default() -> Self {
Resource {
flavor: ResourceFlavor::None,
name: Cow::Borrowed(""),
is_module: false,
is_builtin_extension_module: false,
is_frozen_module: false,
is_extension_module: false,
is_shared_library: false,
is_utf8_filename_data: false,
is_package: false,
is_namespace_package: false,
in_memory_source: None,
in_memory_bytecode: None,
in_memory_bytecode_opt1: None,
in_memory_bytecode_opt2: None,
in_memory_extension_module_shared_library: None,
in_memory_package_resources: None,
in_memory_distribution_resources: None,
in_memory_shared_library: None,
shared_library_dependency_names: None,
relative_path_module_source: None,
relative_path_module_bytecode: None,
relative_path_module_bytecode_opt1: None,
relative_path_module_bytecode_opt2: None,
relative_path_extension_module_shared_library: None,
relative_path_package_resources: None,
relative_path_distribution_resources: None,
file_executable: false,
file_data_embedded: None,
file_data_utf8_relative_path: None,
}
}
}
impl<'a, X> AsRef<Resource<'a, X>> for Resource<'a, X>
where
[X]: ToOwned<Owned = Vec<X>>,
{
fn as_ref(&self) -> &Resource<'a, X> {
self
}
}
impl<'a, X> Resource<'a, X>
where
[X]: ToOwned<Owned = Vec<X>>,
{
pub fn to_owned(&self) -> Resource<'static, X> {
Resource {
flavor: self.flavor,
name: Cow::Owned(self.name.clone().into_owned()),
is_module: self.is_module,
is_builtin_extension_module: self.is_builtin_extension_module,
is_frozen_module: self.is_frozen_module,
is_extension_module: self.is_extension_module,
is_shared_library: self.is_shared_library,
is_utf8_filename_data: self.is_utf8_filename_data,
is_package: self.is_package,
is_namespace_package: self.is_namespace_package,
in_memory_source: self
.in_memory_source
.as_ref()
.map(|value| Cow::Owned(value.clone().into_owned())),
in_memory_bytecode: self
.in_memory_bytecode
.as_ref()
.map(|value| Cow::Owned(value.clone().into_owned())),
in_memory_bytecode_opt1: self
.in_memory_bytecode_opt1
.as_ref()
.map(|value| Cow::Owned(value.clone().into_owned())),
in_memory_bytecode_opt2: self
.in_memory_bytecode_opt2
.as_ref()
.map(|value| Cow::Owned(value.clone().into_owned())),
in_memory_extension_module_shared_library: self
.in_memory_extension_module_shared_library
.as_ref()
.map(|value| Cow::Owned(value.clone().into_owned())),
in_memory_package_resources: self.in_memory_package_resources.as_ref().map(|value| {
HashMap::from_iter(value.iter().map(|(k, v)| {
(
Cow::Owned(k.clone().into_owned()),
Cow::Owned(v.clone().into_owned()),
)
}))
}),
in_memory_distribution_resources: self.in_memory_distribution_resources.as_ref().map(
|value| {
HashMap::from_iter(value.iter().map(|(k, v)| {
(
Cow::Owned(k.clone().into_owned()),
Cow::Owned(v.clone().into_owned()),
)
}))
},
),
in_memory_shared_library: self
.in_memory_source
.as_ref()
.map(|value| Cow::Owned(value.clone().into_owned())),
shared_library_dependency_names: self.shared_library_dependency_names.as_ref().map(
|value| Vec::from_iter(value.iter().map(|x| Cow::Owned(x.clone().into_owned()))),
),
relative_path_module_source: self
.relative_path_module_source
.as_ref()
.map(|value| Cow::Owned(value.clone().into_owned())),
relative_path_module_bytecode: self
.relative_path_module_bytecode
.as_ref()
.map(|value| Cow::Owned(value.clone().into_owned())),
relative_path_module_bytecode_opt1: self
.relative_path_module_bytecode_opt1
.as_ref()
.map(|value| Cow::Owned(value.clone().into_owned())),
relative_path_module_bytecode_opt2: self
.relative_path_module_bytecode_opt2
.as_ref()
.map(|value| Cow::Owned(value.clone().into_owned())),
relative_path_extension_module_shared_library: self
.relative_path_extension_module_shared_library
.as_ref()
.map(|value| Cow::Owned(value.clone().into_owned())),
relative_path_package_resources: self.relative_path_package_resources.as_ref().map(
|value| {
HashMap::from_iter(value.iter().map(|(k, v)| {
(
Cow::Owned(k.clone().into_owned()),
Cow::Owned(v.clone().into_owned()),
)
}))
},
),
relative_path_distribution_resources: self
.relative_path_distribution_resources
.as_ref()
.map(|value| {
HashMap::from_iter(value.iter().map(|(k, v)| {
(
Cow::Owned(k.clone().into_owned()),
Cow::Owned(v.clone().into_owned()),
)
}))
}),
file_executable: self.file_executable,
file_data_embedded: self
.file_data_embedded
.as_ref()
.map(|value| Cow::Owned(value.clone().into_owned())),
file_data_utf8_relative_path: self
.file_data_utf8_relative_path
.as_ref()
.map(|value| Cow::Owned(value.clone().into_owned())),
}
}
}