Compare commits

..

No commits in common. "337b83450f25fc6dfe7ea382d4d3b4a0b8883af3" and "f17bc694ccd59cf374bef243e5489e9302ca2645" have entirely different histories.

25 changed files with 170 additions and 6645 deletions

6294
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,8 @@
[workspace] [workspace]
resolver = "2" resolver = "2"
members = [ members = [
"lua_modules/filesystem", "lua_modules/filesystem"
"lua_modules/rerun_lua"
] ]
[workspace.dependencies] [workspace.dependencies]
mlua = { version = "0.9.1", features = ["lua54", "module", "serde", "serialize"] } mlua = { version = "0.9.1", features = ["lua54", "module"] }

View File

@ -5,10 +5,6 @@ run-fs: (lua "fs.example.lua")
build-filesystem: (_copy-so "dev" "filesystem") build-filesystem: (_copy-so "dev" "filesystem")
deploy-fs: (_deploy "filesystem") deploy-fs: (_deploy "filesystem")
run-rr: (lua "rr.example.lua")
build-rr: (_copy-so "dev" "rerun_lua")
deploy-rr: (_deploy "rerun_lua")
lua file: lua file:
LUA_CPATH=c_modules/?.so lua lua/{{file}} LUA_CPATH=c_modules/?.so lua lua/{{file}}

View File

@ -1,13 +1,77 @@
local fs = require("filesystem") local fs = require("filesystem")
local root = fs.directory(".") local dirs = fs.directory("/Users/kinch/Desktop/Rebuild World")
string.starts_with = function(self, str) local FileTree = {foo = "bar"}
return self:find('^' .. str) ~= nil function FileTree:new(iterator)
local file_tree = {
iterator = iterator,
filters = {}
}
setmetatable(file_tree, self)
self.__index = self
return file_tree
end end
for entry in root do function FileTree:filter(filter_fn)
if not entry.rel_path:starts_with("%.") then table.insert(self.filters, filter_fn)
print(entry.rel_path) return self
end
function FileTree:__call()
local next = self.iterator()
if next == nil then
return nil
end end
end
for k,filter in pairs(self.filters) do
if (not filter(next)) then
return self()
end
end
return next
end
function is_dir(entry)
return entry:is_dir()
end
function starts_with(prefix)
return function(entry)
return entry.path:find("^"..prefix)
end
end
function does_not(predicate)
return function(...) return not predicate(...) end
end
local comic_dir = FileTree:new(fs.directory("."))
comic_dir:filter(is_dir)
for chapter_dir in comic_dir do
FileTree:new(fs.directory(chapter_dir)):filter(does_not(starts_with("./")))
end
--for dir in dirs do
-- if dir:is_dir() then
-- for sub_dir in fs.directory(dir.path) do
-- print(sub_dir)
-- end
-- end
--end
--for dir in dirs do
-- local files = dir:filter {
-- exclude = function(file)
-- return file.is_file and not file.basename:starts_with("._")
-- end
-- }
--
-- zip {
-- from = files,
-- into = dir.basename,
-- extension = "cbz",
-- }
--end

View File

@ -1,64 +0,0 @@
local rr = require("rerun_lua")
function bbox(ms_ocr_bbox)
return rr.rect_xyxy {
ms_ocr_bbox[1],
ms_ocr_bbox[2],
ms_ocr_bbox[5],
ms_ocr_bbox[6],
}
end
function paragraphs(ms_form_result)
local result = {}
for _, paragraph in ipairs(ms_form_result.analyzeResult.paragraphs) do
for _, region in ipairs(paragraph.boundingRegions) do
table.insert(result, {
text = paragraph.content,
page = region.pageNumber,
bbox = bbox(region.polygon)
})
end
end
return result
end
function lines(ms_form_result)
local result = {}
for _, page in ipairs(ms_form_result.analyzeResult.pages) do
for _, line in ipairs(page.lines) do
table.insert(result, {
text = line.content,
page = page.pageNumber,
bbox = bbox(line.polygon)
})
end
end
return result
end
function words(ms_form_result)
local result = {}
for _, page in ipairs(ms_form_result.analyzeResult.pages) do
for _, word in ipairs(page.words) do
table.insert(result, {
text = word.content,
page = page.pageNumber,
bbox = bbox(word.polygon)
})
end
end
return result
end
local ms_form = rr.json("/Users/tbr/Desktop/ms_form.json")
local record = rr.recording("example-2")
record:image("54-0", "/Users/tbr/Desktop/00054-0.png")
record:text_objects("54-0/ms-forms/paragraphs",paragraphs(ms_form))
record:text_objects("54-0/ms-forms/lines",lines(ms_form))
record:text_objects("54-0/ms-forms/words",words(ms_form))

View File

@ -7,7 +7,4 @@ edition = "2021"
crate-type = ["cdylib"] crate-type = ["cdylib"]
[dependencies] [dependencies]
thiserror = "1.0.48" mlua = { workspace = true }
mlua = { workspace = true }
zip = "0.6"
walkdir = "2.4.0"

View File

@ -1,41 +0,0 @@
use crate::driver_filesystem::filesystem_resource::FilesystemResourceLocation;
use crate::resource::{DynResource, DynResourceLocation, Resource, ResourceLocation};
use crate::source::ResourceSource;
use std::fs::rename;
use std::io::Sink;
use std::path::PathBuf;
use walkdir::WalkDir;
pub struct DirectorySource {
location: String,
iter: walkdir::IntoIter,
}
impl DirectorySource {
pub fn open_dir(location: String) -> Self {
let iter = WalkDir::new(location.clone()).into_iter();
DirectorySource { location, iter }
}
}
impl ResourceSource for DirectorySource {
fn location(&self) -> DynResourceLocation {
Box::new(FilesystemResourceLocation::from(PathBuf::from(
self.location.clone(),
)))
}
}
impl Iterator for DirectorySource {
type Item = DynResourceLocation;
fn next(&mut self) -> Option<Self::Item> {
use crate::resource::ResourceLocation;
self.iter
.next()
.map(|entry| entry.unwrap())
.map(|entry| entry.path().strip_prefix("./").unwrap().to_path_buf())
.map(|entry| {
let loc = FilesystemResourceLocation::from(entry);
Box::new(loc) as Box<dyn ResourceLocation>
})
}
}

View File

@ -1,18 +0,0 @@
use crate::resource::ResourceLocation;
use std::path::PathBuf;
pub struct FilesystemResourceLocation {
path: PathBuf,
}
impl ResourceLocation for FilesystemResourceLocation {
fn location(&self) -> String {
self.path.display().to_string()
}
}
impl From<PathBuf> for FilesystemResourceLocation {
fn from(path: PathBuf) -> Self {
FilesystemResourceLocation { path }
}
}

View File

@ -1,2 +0,0 @@
pub mod directory_source;
pub mod filesystem_resource;

View File

@ -1,8 +0,0 @@
use crate::sink::ResourceSink;
use std::iter::Zip;
mod zip_zink;
pub struct ZipZink {}
impl ResourceSink for ZipZink {}

View File

@ -1,16 +0,0 @@
use mlua::prelude::{LuaError, LuaResult};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum FsError {
#[error("fs error happened: {msg}")]
GenericError { msg: String },
}
pub type Res<T = ()> = Result<T, FsError>;
impl From<FsError> for LuaError {
fn from(fs_error: FsError) -> Self {
LuaError::RuntimeError(fs_error.to_string())
}
}

View File

@ -1,19 +1,11 @@
mod driver_filesystem; mod types;
mod driver_zip_archive;
mod error;
mod lua_bindings;
mod operations;
mod resource;
mod sink;
mod source;
use crate::source::DynResourceSource; use crate::types::file_tree::*;
use driver_filesystem::directory_source::DirectorySource;
use mlua::prelude::*; use mlua::prelude::*;
fn directory(lua: &Lua, path: String) -> LuaResult<DynResourceSource> { fn directory(lua: &Lua, path: String) -> LuaResult<DirectoryFileTreeIter> {
let source = DirectorySource::open_dir(path); let read_dir = std::fs::read_dir(path).unwrap();
Ok(Box::new(source)) Ok(DirectoryFileTreeIter { read_dir })
} }
#[mlua::lua_module] #[mlua::lua_module]

View File

@ -1,5 +0,0 @@
use crate::resource::DynResourceLocation;
use mlua::{MetaMethod, UserData, UserDataFields, UserDataMethods};
mod resource_bindings;
mod source_bindings;

View File

@ -1,12 +0,0 @@
use crate::resource::DynResourceLocation;
use mlua::{MetaMethod, UserData, UserDataFields, UserDataMethods};
impl UserData for DynResourceLocation {
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("rel_path", |lua, this| Ok(this.location()))
}
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_method_mut(MetaMethod::ToString, |lua, this, _: ()| Ok(this.location()));
}
}

View File

@ -1,8 +0,0 @@
use crate::source::DynResourceSource;
use mlua::{MetaMethod, UserData, UserDataMethods};
impl UserData for DynResourceSource {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_method_mut(MetaMethod::Call, |lua, this, _: ()| Ok(this.next()));
}
}

View File

@ -1 +0,0 @@
mod operation_copy;

View File

@ -1,4 +0,0 @@
use crate::sink::DynResourceSink;
use crate::source::DynResourceSource;
pub fn copy_operation(from: DynResourceSource, to: DynResourceSink) {}

View File

@ -1,17 +0,0 @@
use crate::sink::ResourceSink;
use crate::source::ResourceSource;
/// Points to a resource. Think of it as a path.
pub trait ResourceLocation {
fn location(&self) -> String;
}
/// A concrete resource. Think of as a directory or a file
pub trait Resource {}
// A resource ready to be read. Think of it as a open file for reading
pub trait ResourceInputStream: std::io::Read {}
// A resource ready to be written. Think of it as a open file for reading
pub trait ResourceOutputStream: std::io::Write {}
pub type DynResource = Box<dyn Resource>;
pub type DynResourceLocation = Box<dyn ResourceLocation>;
pub type DynResourceInputStream = Box<dyn ResourceInputStream>;
pub type DynResourceOutputStream = Box<dyn ResourceOutputStream>;

View File

@ -1,8 +0,0 @@
// mod zip_sink;
use crate::resource::{Resource, ResourceInputStream};
pub trait ResourceSink {
// fn add_file(&mut self, input_stream: DynResourceInputStream) {}
}
pub type DynResourceSink = Box<dyn ResourceSink>;

View File

@ -1,5 +0,0 @@
use crate::resource::{DynResource, DynResourceLocation};
pub trait ResourceSource: Iterator<Item = DynResourceLocation> {
fn location(&self) -> DynResourceLocation;
}
pub type DynResourceSource = Box<dyn ResourceSource<Item = DynResourceLocation>>;

View File

@ -0,0 +1,87 @@
use crate::types::file_tree::ResourceType::{Directory, RegularFile};
use mlua::{MetaMethod, UserData, UserDataFields, UserDataMethods};
use std::fs::{DirEntry, FileType, ReadDir};
use std::path::PathBuf;
pub enum ResourceType {
Directory,
RegularFile,
}
impl From<FileType> for ResourceType {
fn from(file_type: FileType) -> Self {
if file_type.is_file() {
RegularFile
} else {
Directory
}
}
}
pub trait Resource {
fn path(&self) -> String;
fn file_type(&self) -> ResourceType;
fn is_dir(&self) -> bool {
if let Directory = self.file_type() {
true
} else {
false
}
}
fn is_file(&self) -> bool {
if let RegularFile = self.file_type() {
true
} else {
false
}
}
}
pub struct FileSystemResource {
path: PathBuf,
}
impl Resource for FileSystemResource {
fn path(&self) -> String {
self.path.display().to_string()
}
fn file_type(&self) -> ResourceType {
self.path.metadata().unwrap().file_type().into()
}
}
pub trait FileTreeIter<RES: Resource>: Iterator<Item = RES> {}
pub struct DirectoryFileTreeIter {
pub read_dir: ReadDir,
}
impl Iterator for DirectoryFileTreeIter {
type Item = FileSystemResource;
fn next(&mut self) -> Option<Self::Item> {
self.read_dir.next().map(|entry| entry.unwrap().into())
}
}
impl From<DirEntry> for FileSystemResource {
fn from(value: DirEntry) -> Self {
FileSystemResource { path: value.path() }
}
}
impl UserData for DirectoryFileTreeIter {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_method_mut(MetaMethod::Call, |lua, dir_iter, _: ()| Ok(dir_iter.next()));
}
}
impl UserData for FileSystemResource {
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("path", |lua, fsr| Ok(fsr.path.display().to_string()))
}
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::ToString, |lua, fsr, _: ()| Ok(fsr.path()));
methods.add_method("is_dir", |lua, fsr, _: ()| Ok(fsr.is_dir()));
methods.add_method("is_file", |lua, fsr, _: ()| Ok(fsr.is_file()));
}
}

View File

@ -0,0 +1 @@
pub mod file_tree;

View File

@ -1,15 +0,0 @@
[package]
name = "rerun_lua"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
image = { version = "0.24.7", features = ["png", "jpeg", "tiff"] }
mlua = { workspace = true }
rerun = "0.8.2"
serde_json = "1.0.107"
serde = { version = "1.0.188", features = ["derive"] }

View File

@ -1,99 +0,0 @@
use std::fs::File;
use std::io::BufReader;
use std::path::PathBuf;
use mlua::{AnyUserData, Function, MetaMethod, Table, TableExt, UserData, UserDataRef};
use mlua::prelude::*;
use rerun::{MsgSender, RecordingStream, RecordingStreamBuilder};
use rerun::components::{Rect2D, Tensor, Vec4D};
use serde::{Deserialize, Serialize};
#[derive(Debug)]
pub struct TextObject {
pub text: String,
pub bbox: Rect2D,
}
impl UserData for TextObject {
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::ToString, |_lua, this, _:()| {
Ok(format!("{:?}", this))
})
}
}
impl<'lua> FromLua<'lua> for TextObject {
fn from_lua(value: LuaValue<'lua>, lua: &'lua Lua) -> LuaResult<Self> {
let table = value.as_table().ok_or(LuaError::RuntimeError("invalid args for text_object".to_string()))?;
let rect = table.get::<_, UserDataRef<Rect2D>>("bbox")?.clone();
Ok(TextObject {
text: table.get("text")?,
bbox: rect
})
}
}
fn json(lua: &Lua, path: String) -> LuaResult<LuaValue> {
let file = File::open(path.as_str())
.map_err(|error| LuaError::RuntimeError(format!("could not open json path: {path}. Error: {error}")))?;
let reader = BufReader::new(file);
let json_value: serde_json::Value = serde_json::from_reader(reader)
.map_err(|error| LuaError::RuntimeError(format!("could not parse json at: {path}. Error: {error}")))?;
lua.to_value(&json_value)
}
fn recording(lua: &Lua, name: String) -> LuaResult<AnyUserData> {
let stream = RecordingStreamBuilder::new(name)
.connect(rerun::default_server_addr(), None)
.map_err(|err| LuaError::RuntimeError(err.to_string()))?;
lua.create_any_userdata(stream)
}
fn rect_xyxy(lua: &Lua, points: [f32;4]) -> LuaResult<AnyUserData> {
let rect = Rect2D::XYXY(Vec4D(points).into());
lua.create_any_userdata(rect)
}
fn register_bindings(lua: &Lua) -> LuaResult<()> {
lua.register_userdata_type::<Rect2D>(|reg| {
reg.add_meta_method(MetaMethod::ToString, |lua, this, _:()| Ok(format!("{:?}", this)))
})?;
lua.register_userdata_type::<RecordingStream>(|reg|{
reg.add_method("image", |lua, this, (entity_path, image_path): (String,String)| {
let image_tensor = Tensor::from_image_file(PathBuf::from(image_path.as_str()).as_path())
.map_err(|error| LuaError::RuntimeError(format!("Could not read image file {image_path}. Error: {error}")))?;
MsgSender::new(entity_path)
.with_timeless(true)
.with_component(&[image_tensor])
.map_err(|error| LuaError::RuntimeError(format!("Could not send message: {}", error)))?
.send(this)
.map_err(|error| LuaError::RuntimeError(format!("Could not send message {error}")))?;
Ok(())
});
reg.add_method("text_objects", |lua, this, (entity_path, objects): (String, Vec<TextObject>)| {
let rects: Vec<Rect2D> = objects.into_iter()
.map(|t| t.bbox)
.collect();
MsgSender::new(entity_path)
.with_timeless(true)
.with_component(rects.as_slice())
.map_err(|error| LuaError::RuntimeError(format!("Could not send message: {}", error)))?
.send(this)
.map_err(|error| LuaError::RuntimeError(format!("Could not send message {error}")))?;
Ok(())
})
})?;
Ok(())
}
#[mlua::lua_module]
fn rerun_lua(lua: &Lua) -> LuaResult<LuaTable> {
register_bindings(lua)?;
let exports = lua.create_table()?;
exports.set("recording", lua.create_function(recording)?)?;
exports.set("json", lua.create_function(json)?)?;
exports.set("rect_xyxy", lua.create_function(rect_xyxy)?)?;
Ok(exports)
}