-
-
Save Mause/888ad36325f462641a8e169f6183834a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/target |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import struct | |
import os | |
from os.path import expanduser | |
from argparse import ArgumentParser | |
import json | |
import base64 | |
parser = ArgumentParser() | |
parser.add_argument("filename", type=str) | |
parser.add_argument("--extension-version", type=str) | |
parser.add_argument("--duckdb-version", type=str) | |
parser.add_argument("--platform", type=str) | |
parser.add_argument("--metadata-version", type=str, default="4") | |
args = parser.parse_args() | |
format_string = struct.Struct(("32x" * 4) + ("32s" * 4) + "256s") | |
def read_metadata(filename): | |
def try_decode(field): | |
try: | |
return field.decode().strip("\x00") | |
except UnicodeDecodeError: | |
return field | |
with open(filename, "rb") as f: | |
f.seek(-format_string.size, os.SEEK_END) | |
extension_version, duckdb_version, platform, metadata_version, signature = ( | |
try_decode(field) | |
for field in format_string.unpack(f.read(format_string.size)) | |
) | |
return { | |
"extension_version": extension_version, | |
"duckdb_version": duckdb_version, | |
"platform": platform, | |
"metadata_version": metadata_version, | |
"signature": signature, | |
} | |
def write_metadata(filename): | |
fields = ( | |
args.extension_version, | |
args.duckdb_version, | |
args.platform, | |
args.metadata_version, | |
"\x00" * 256, # signature | |
) | |
if not all(fields): | |
parser.error("All fields must be provided") | |
print(fields) | |
encoded = format_string.pack(*(field.encode() for field in fields)) | |
with open(filename, "ab") as f: | |
f.write(encoded) | |
def main(): | |
filename = expanduser(args.filename) | |
if not os.path.exists(filename): | |
parser.error(f"File {filename} does not exist") | |
if args.extension_version: | |
print(f"Extension version: {args.extension_version}") | |
print(f"DuckDB version: {args.duckdb_version}") | |
print(f"Platform: {args.platform}") | |
print(f"Metadata version: {args.metadata_version}") | |
if ( | |
input("Do you want to write this metadata to the file? (y/n) ").lower() | |
== "y" | |
): | |
write_metadata(filename) | |
else: | |
breakpoint() | |
print( | |
json.dumps( | |
read_metadata(filename), | |
default=lambda item: base64.b64encode(item).decode(), | |
indent=2, | |
) | |
) | |
if __name__ == "__main__": | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This file is automatically @generated by Cargo. | |
# It is not intended for manual editing. | |
version = 3 | |
[[package]] | |
name = "anstream" | |
version = "0.6.14" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" | |
dependencies = [ | |
"anstyle", | |
"anstyle-parse", | |
"anstyle-query", | |
"anstyle-wincon", | |
"colorchoice", | |
"is_terminal_polyfill", | |
"utf8parse", | |
] | |
[[package]] | |
name = "anstyle" | |
version = "1.0.7" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" | |
[[package]] | |
name = "anstyle-parse" | |
version = "0.2.4" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" | |
dependencies = [ | |
"utf8parse", | |
] | |
[[package]] | |
name = "anstyle-query" | |
version = "1.1.0" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" | |
dependencies = [ | |
"windows-sys", | |
] | |
[[package]] | |
name = "anstyle-wincon" | |
version = "3.0.3" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" | |
dependencies = [ | |
"anstyle", | |
"windows-sys", | |
] | |
[[package]] | |
name = "append_metadata" | |
version = "0.1.0" | |
dependencies = [ | |
"clap", | |
] | |
[[package]] | |
name = "clap" | |
version = "4.5.7" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" | |
dependencies = [ | |
"clap_builder", | |
"clap_derive", | |
] | |
[[package]] | |
name = "clap_builder" | |
version = "4.5.7" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" | |
dependencies = [ | |
"anstream", | |
"anstyle", | |
"clap_lex", | |
"strsim", | |
] | |
[[package]] | |
name = "clap_derive" | |
version = "4.5.5" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" | |
dependencies = [ | |
"heck", | |
"proc-macro2", | |
"quote", | |
"syn", | |
] | |
[[package]] | |
name = "clap_lex" | |
version = "0.7.1" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" | |
[[package]] | |
name = "colorchoice" | |
version = "1.0.1" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" | |
[[package]] | |
name = "heck" | |
version = "0.5.0" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" | |
[[package]] | |
name = "is_terminal_polyfill" | |
version = "1.70.0" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" | |
[[package]] | |
name = "proc-macro2" | |
version = "1.0.85" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" | |
dependencies = [ | |
"unicode-ident", | |
] | |
[[package]] | |
name = "quote" | |
version = "1.0.36" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" | |
dependencies = [ | |
"proc-macro2", | |
] | |
[[package]] | |
name = "strsim" | |
version = "0.11.1" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" | |
[[package]] | |
name = "syn" | |
version = "2.0.66" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" | |
dependencies = [ | |
"proc-macro2", | |
"quote", | |
"unicode-ident", | |
] | |
[[package]] | |
name = "unicode-ident" | |
version = "1.0.12" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" | |
[[package]] | |
name = "utf8parse" | |
version = "0.2.2" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" | |
[[package]] | |
name = "windows-sys" | |
version = "0.52.0" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" | |
dependencies = [ | |
"windows-targets", | |
] | |
[[package]] | |
name = "windows-targets" | |
version = "0.52.5" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" | |
dependencies = [ | |
"windows_aarch64_gnullvm", | |
"windows_aarch64_msvc", | |
"windows_i686_gnu", | |
"windows_i686_gnullvm", | |
"windows_i686_msvc", | |
"windows_x86_64_gnu", | |
"windows_x86_64_gnullvm", | |
"windows_x86_64_msvc", | |
] | |
[[package]] | |
name = "windows_aarch64_gnullvm" | |
version = "0.52.5" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" | |
[[package]] | |
name = "windows_aarch64_msvc" | |
version = "0.52.5" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" | |
[[package]] | |
name = "windows_i686_gnu" | |
version = "0.52.5" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" | |
[[package]] | |
name = "windows_i686_gnullvm" | |
version = "0.52.5" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" | |
[[package]] | |
name = "windows_i686_msvc" | |
version = "0.52.5" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" | |
[[package]] | |
name = "windows_x86_64_gnu" | |
version = "0.52.5" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" | |
[[package]] | |
name = "windows_x86_64_gnullvm" | |
version = "0.52.5" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" | |
[[package]] | |
name = "windows_x86_64_msvc" | |
version = "0.52.5" | |
source = "registry+https://github.com/rust-lang/crates.io-index" | |
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "append_metadata" | |
version = "0.1.0" | |
edition = "2021" | |
[dependencies] | |
clap = { version = "4.5.7", features = ["derive"] } | |
[[bin]] | |
name = "append_metadata" | |
path = "rust.rs" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use clap::Parser; | |
use std::io::{Read, Seek, SeekFrom, Write}; | |
use std::{ffi::CStr, fs::OpenOptions}; | |
#[repr(C)] | |
#[derive(Debug)] | |
struct Metadata { | |
extension_version: [u8; 32], | |
duckdb_version: [u8; 32], | |
platform: [u8; 32], | |
metadata_version: [u8; 32], | |
signature: [u8; 256], | |
} | |
impl Metadata { | |
fn read_metadata(filename: &str) -> Result<Metadata, std::io::Error> { | |
let mut file = OpenOptions::new().read(true).open(filename)?; | |
file.seek(SeekFrom::End(-(std::mem::size_of::<Metadata>() as i64)))?; | |
let mut metadata = Metadata { | |
extension_version: [0; 32], | |
duckdb_version: [0; 32], | |
platform: [0; 32], | |
metadata_version: [0; 32], | |
signature: [0; 256], | |
}; | |
file.read_exact(unsafe { | |
std::slice::from_raw_parts_mut( | |
metadata.extension_version.as_mut_ptr() as *mut u8, | |
std::mem::size_of_val(&metadata), | |
) | |
})?; | |
Ok(metadata) | |
} | |
fn write_metadata(filename: &str, metadata: Metadata) -> Result<(), std::io::Error> { | |
let mut file = OpenOptions::new().append(true).open(filename)?; | |
let bytes = unsafe { | |
std::slice::from_raw_parts( | |
(&metadata as *const Metadata) as *const u8, | |
std::mem::size_of_val(&metadata), | |
) | |
}; | |
file.write_all(bytes)?; | |
Ok(()) | |
} | |
} | |
#[derive(Debug, clap::Parser)] | |
struct Args { | |
#[clap(subcommand)] | |
subcommand: Subcommand, | |
} | |
#[derive(clap::Parser, Debug)] | |
enum Subcommand { | |
Read(ReadCommand), | |
Write(WriteCommand), | |
} | |
#[derive(clap::Parser, Debug)] | |
struct ReadCommand { | |
filename: String, | |
} | |
#[derive(clap::Parser, Debug)] | |
struct WriteCommand { | |
filename: String, | |
#[clap(short, long)] | |
extension_version: String, | |
#[clap(short, long)] | |
duckdb_version: String, | |
#[clap(short, long)] | |
platform: String, | |
#[clap(short, long, default_value = "4")] | |
metadata_version: String, | |
} | |
fn main() -> Result<(), Box<dyn std::error::Error>> { | |
let args = Args::parse(); | |
match args.subcommand { | |
Subcommand::Read(read) => read_metadata(&read.filename), | |
Subcommand::Write(write) => write_metadata(&write.filename, &write), | |
} | |
} | |
fn load(data: [u8; 32]) -> Result<String, Box<dyn std::error::Error>> { | |
let cstr = CStr::from_bytes_until_nul(&data)?; | |
Ok(cstr.to_str()?.to_string()) | |
} | |
fn read_metadata(filename: &str) -> Result<(), Box<dyn std::error::Error>> { | |
let metadata = Metadata::read_metadata(filename)?; | |
println!("extension_version: {:?}", load(metadata.extension_version)?); | |
println!("duckdb_version: {:?}", load(metadata.duckdb_version)?); | |
println!("platform: {:?}", load(metadata.platform)?); | |
println!("metadata_version: {:?}", load(metadata.metadata_version)?); | |
Ok(()) | |
} | |
fn write_metadata(filename: &str, args: &WriteCommand) -> Result<(), Box<dyn std::error::Error>> { | |
let metadata = Metadata { | |
extension_version: args.extension_version.as_bytes().try_into()?, | |
duckdb_version: args.duckdb_version.as_bytes().try_into()?, | |
platform: args.platform.as_bytes().try_into()?, | |
metadata_version: args.metadata_version.as_bytes().try_into()?, | |
signature: [0; 256], | |
}; | |
Metadata::write_metadata(filename, metadata).expect("Failed to write metadata"); | |
Ok(()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment