How to make Custom File Format for Rust App? - rust

I'm creating a Rust app that needs to save and load files with its own custom file format, similar to Photoshop and Illustrator save/load to .psd and .ai files, respectively.
How do I go about "defining" my own file format so that the OS recognizes it and will use my app to open this file format (.mtp is the filetype's extension name)?
How do I develop a means of parsing this file format in my app?
In reality, my app is saving to a JSON style structure via Serde. I want this file extension to distinguish the file type as something unique to my app so that users don't load random .json files into the app.
struct MyApp{
name: String,
content: String,
}
impl MyApp{
save_file(&self, path: String)->std::io::Result<()>{
let mut file = std::fs:File::create(path)?;
Ok(())
}
load_file(&self, path: String)->std::io::Result<()>{
let mut file = std::fs:File::open(path)?;
//do something with the file
Ok(())
}
}
fn main(){
//using my own custom .mtp format
let app = MyApp{
name: "CoolApp".to_string(),
content: "some information".to_string(),
}
app.save_fle("output/my_path.mtp");
app.load_file("output/my_path.mtp");
}

Related

Access bevy asset right after loading via AssetServer

Is it possible to access a bevy asset right after it was loaded from the AssetServer?
I've read actual loading happens in the background but couldn't find in either official documentation or the bevy cheat book if it is possible to wait for the actual loading to happen inside the same function?
Example of what I'm trying to do
fn f(asset_server: Res<AssetServer>, image_assets: Res<Assets<Image>>,) {
let image: Handle<Image> = assert_server.load("img.png");
// wait for `image` to be loaded...
// NOTE: that this doesn't work - it just goes into an infinite loop
while asset_server.get_load_state(&image) != LoadState::Loaded { }
let image_asset = image_assets.get(&image).unwrap();
}
The reason I need this is to check some of the image's data, for example it's size.
As you probably shouldn't be halting the function for the asynchronous load of the file. Maybe you can create some Entity with the handle. You could have another system running a query for this entity and consume the entity when the handle shows the image is loaded.
Looking it up this appears to be a suggested pattern in the unoffical bevy book.
#[derive(Resource)]
struct AssetsLoading(Vec<HandleUntyped>);
fn setup(server: Res<AssetServer>, mut loading: ResMut<AssetsLoading>) {
// we can have different asset types
let font: Handle<Font> = server.load("my_font.ttf");
let menu_bg: Handle<Image> = server.load("menu.png");
let scene: Handle<Scene> = server.load("level01.gltf#Scene0");
// add them all to our collection for tracking
loading.0.push(font.clone_untyped());
loading.0.push(menu_bg.clone_untyped());
loading.0.push(scene.clone_untyped());
}
fn check_assets_ready(
mut commands: Commands,
server: Res<AssetServer>,
loading: Res<AssetsLoading>
) {
use bevy::asset::LoadState;
match server.get_group_load_state(loading.0.iter().map(|h| h.id)) {
LoadState::Failed => {
// one of our assets had an error
}
LoadState::Loaded => {
// all assets are now ready
// this might be a good place to transition into your in-game state
// remove the resource to drop the tracking handles
commands.remove_resource::<AssetsLoading>();
// (note: if you don't have any other handles to the assets
// elsewhere, they will get unloaded after this)
}
_ => {
// NotLoaded/Loading: not fully ready yet
}
}
}

JSON to JSON conversion using Liquid templates as maps in Azure Logic Apps

this is my JSON source file format
{
"BookingId":2,
"BookingReferenceNumber":"A15",
"BookingIndex":3
}
This is Liquid file for mapping
{
"Id":{{content.BookingId}},
"refNumber":"{{content.BookingReferenceNumber}}",
"Index":{{content.BookingIndex}}
}
JSON Output file should be like this
{
"Id":2,
"refNumber":"A15",
"Index":3
}
But I am getting JSON output without content
{
"Id":"",
"refNumber":"",
"Index":""
}
Please suggest proper liquid file format

What does `::parse()` do on a struct?

I'm learning rust, and the best way to learn a programming language is obviously reading and understanding other's code. Now I faced this line I am not able to understand even after reading docs, other source files and googling for it :
In zoxide's main file, there's this line :
if let Err(e) = App::parse().run() { ... }
What does App::parse() mean ? App is a structure and not a variable, so I understand why it's not .parse(), but why ::parse() and what does it do ? (I couldn't find its definition in app's source code (nor in this file))
First, both the files you mentioned are not the App that zoxide is including. zoxide's main.rs file says use crate::app::{App, Run};, so it's including App from src/app/mod.rs, which exports App from src/app/_app.rs
In that file, we can see the declaration of App:
#[derive(Debug, Clap)]
#[clap(
bin_name = env!("CARGO_PKG_NAME"),
about,
author,
after_help = ENV_HELP,
global_setting(AppSettings::ColoredHelp),
global_setting(AppSettings::DisableHelpSubcommand),
global_setting(AppSettings::DisableVersionForSubcommands),
global_setting(AppSettings::PropagateVersion),
version = option_env!("ZOXIDE_VERSION").unwrap_or_default()
)]
pub enum App {
Add(Add),
Import(Import),
Init(Init),
Query(Query),
Remove(Remove),
}
The key in this case is #[derive(Clap)]. If you look at the clap crate you'll see that it's a crate for parsing command line parameters, and deriving from Clap adds a parse method to the structure.

nodejs import file and use functions natively

How can I import/require a file, and then use the functions in the file natively?
Say I have file 1:
const file2 = require("./file2.js")
const text = "hello"
file2.print()
And in file 2 I have:
module.exports = {
print:()=>{
console.log(text)
}
}
I want to be able to use functions from another file as if they were in the original file, retaining the variables and objects created in the first file, is this possible?
No, the modules are separate, unless you resort to assigning your variables into the global object and hoping that you can keep track of them without going insane. Don't do that.
Either
pass the data you need around (the best option most of the time), or
maybe add a third module containing the shared state you need and require() it from both file 1 and file 2
No!
But
The regular pattern of shared context is that you create a context and share it. The most simple form of it is something like this:
//In file 1 -->
let myContext = {
text: 'hello'
}
file2.print(myContext);
//In file 2 -->
module.exports = {
print:(ctx)=>{
console.log(ctx.text)
}
}
However
JS has some inbuilt support for context. Something like this:
//In file 1 -->
let myContext = {
text: 'hello'
}
let print = file2.print.bind(myContext);
print();
//In file 2 -->
module.exports = {
print: function(){
console.log(this.text)
}
}
Notice the removal of the argument and changing the arrow function to a function expression.

gradle get relative resource path

When I iterate over source repository I do like this
def resourceDir = proj.sourceSets.main.output.resourcesDir
resourceDir.eachFileRecurse(groovy.io.FileType.FILES) { // only files will be recognized
file ->
def path = FilenameUtils.separatorsToUnix(file.toString())
if (FilenameUtils.getExtension(file.toString()) in supportedResourceExt) {
proj.logger.lifecycle("Reading file {}.", file)
//.....
}
}
In log it writes this
Reading file D:\PROJECT_FOLDER\project\subproject\subsubproject\build\resources\main\com\package\something\file.txt
How to get only the part starting with com\package\something\file.txt without explicitly reading it like file.substring(file.indexOf)?
Maybe it's posible to relativize it with project path somehow?
It seems that:
proj.logger.lifecycle("Reading file {}.", file.absolutePath - resourceDir.absolutePath)
should work. Can't check it right now.

Resources