mirror of
https://github.com/132nd-vWing/tacview-splitter.git
synced 2026-08-26 07:48:37 +02:00
first commit
This commit is contained in:
+118
@@ -11,3 +11,121 @@ Cargo.lock
|
|||||||
# These are backup files generated by rustfmt
|
# These are backup files generated by rustfmt
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
|
|
||||||
|
*.txt.acmi
|
||||||
|
*.zip.acmi
|
||||||
|
testfiles
|
||||||
|
perf.data*
|
||||||
|
flamegraph*svg
|
||||||
|
|
||||||
|
|
||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/intellij
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=intellij
|
||||||
|
|
||||||
|
### Intellij ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
.idea/**/aws.xml
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
|
### Intellij Patch ###
|
||||||
|
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
||||||
|
|
||||||
|
# *.iml
|
||||||
|
# modules.xml
|
||||||
|
# .idea/misc.xml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# Sonarlint plugin
|
||||||
|
# https://plugins.jetbrains.com/plugin/7973-sonarlint
|
||||||
|
.idea/**/sonarlint/
|
||||||
|
|
||||||
|
# SonarQube Plugin
|
||||||
|
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
|
||||||
|
.idea/**/sonarIssues.xml
|
||||||
|
|
||||||
|
# Markdown Navigator plugin
|
||||||
|
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
|
||||||
|
.idea/**/markdown-navigator.xml
|
||||||
|
.idea/**/markdown-navigator-enh.xml
|
||||||
|
.idea/**/markdown-navigator/
|
||||||
|
|
||||||
|
# Cache file creation bug
|
||||||
|
# See https://youtrack.jetbrains.com/issue/JBR-2257
|
||||||
|
.idea/$CACHE_FILE$
|
||||||
|
|
||||||
|
# CodeStream plugin
|
||||||
|
# https://plugins.jetbrains.com/plugin/12206-codestream
|
||||||
|
.idea/codestream.xml
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/intellij
|
||||||
|
|
||||||
|
|||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
<inspection_tool class="PyCompatibilityInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="ourVersions">
|
||||||
|
<value>
|
||||||
|
<list size="3">
|
||||||
|
<item index="0" class="java.lang.String" itemvalue="3.8" />
|
||||||
|
<item index="1" class="java.lang.String" itemvalue="3.9" />
|
||||||
|
<item index="2" class="java.lang.String" itemvalue="3.10" />
|
||||||
|
</list>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PyPep8Inspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||||
|
<option name="ignoredErrors">
|
||||||
|
<list>
|
||||||
|
<option value="E265" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
||||||
Generated
+4
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/tacview-splitter.iml" filepath="$PROJECT_DIR$/.idea/tacview-splitter.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+11
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
+88
@@ -0,0 +1,88 @@
|
|||||||
|
pub mod lib {
|
||||||
|
use std::io::Write;
|
||||||
|
use std::fs;
|
||||||
|
use zip;
|
||||||
|
|
||||||
|
const ERR_CANNOT_WRITE_DATA: &str = "Could not write data";
|
||||||
|
|
||||||
|
pub struct IDs<'a> {
|
||||||
|
pub blue: Vec<&'a str>,
|
||||||
|
pub red: Vec<&'a str>,
|
||||||
|
pub violet: Vec<&'a str>,
|
||||||
|
pub unknown: Vec<&'a str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DescriptorsZip {
|
||||||
|
blue: zip::ZipWriter<fs::File>,
|
||||||
|
red: zip::ZipWriter<fs::File>,
|
||||||
|
violet: zip::ZipWriter<fs::File>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DescriptorsTxt {
|
||||||
|
pub blue: fs::File,
|
||||||
|
pub red: fs::File,
|
||||||
|
pub violet: fs::File,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OutputFilenames {
|
||||||
|
pub txt: FilenamesVariant,
|
||||||
|
pub zip: FilenamesVariant,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FilenamesVariant {
|
||||||
|
pub blue: String,
|
||||||
|
pub red: String,
|
||||||
|
pub violet: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BodiesByCoalition<'a> {
|
||||||
|
pub blue: Vec<&'a str>,
|
||||||
|
pub red: Vec<&'a str>,
|
||||||
|
pub violet: Vec<&'a str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait WriteData {
|
||||||
|
fn write(&mut self, header: Vec<String>, bodies_by_coalition: BodiesByCoalition);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WriteData for DescriptorsTxt {
|
||||||
|
fn write(&mut self, header: Vec<String>, bodies_by_coalition: BodiesByCoalition) {
|
||||||
|
for line in &header {
|
||||||
|
write!(self.blue, "{}\n", line).expect(ERR_CANNOT_WRITE_DATA);
|
||||||
|
write!(self.red, "{}\n", line).expect(ERR_CANNOT_WRITE_DATA);
|
||||||
|
write!(self.violet, "{}\n", line).expect(ERR_CANNOT_WRITE_DATA);
|
||||||
|
}
|
||||||
|
for line in &bodies_by_coalition.blue {
|
||||||
|
write!(self.blue, "{}\n", line).expect(ERR_CANNOT_WRITE_DATA);
|
||||||
|
}
|
||||||
|
for line in &bodies_by_coalition.red {
|
||||||
|
write!(self.red, "{}\n", line).expect(ERR_CANNOT_WRITE_DATA);
|
||||||
|
}
|
||||||
|
for line in &bodies_by_coalition.violet {
|
||||||
|
write!(self.violet, "{}\n", line).expect(ERR_CANNOT_WRITE_DATA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WriteData for DescriptorsZip {
|
||||||
|
fn write(&mut self, header: Vec<String>, bodies_by_coalition: BodiesByCoalition) {
|
||||||
|
for line in &header {
|
||||||
|
write!(self.blue, "{}\n", line).expect(ERR_CANNOT_WRITE_DATA);
|
||||||
|
write!(self.red, "{}\n", line).expect(ERR_CANNOT_WRITE_DATA);
|
||||||
|
write!(self.violet, "{}\n", line).expect(ERR_CANNOT_WRITE_DATA);
|
||||||
|
}
|
||||||
|
for line in &bodies_by_coalition.blue {
|
||||||
|
write!(self.blue, "{}\n", line).expect(ERR_CANNOT_WRITE_DATA);
|
||||||
|
}
|
||||||
|
for line in &bodies_by_coalition.red {
|
||||||
|
write!(self.red, "{}\n", line).expect(ERR_CANNOT_WRITE_DATA);
|
||||||
|
}
|
||||||
|
for line in &bodies_by_coalition.violet {
|
||||||
|
write!(self.violet, "{}\n", line).expect(ERR_CANNOT_WRITE_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
use std::{fs, str};
|
||||||
|
|
||||||
|
use std::io::{BufRead, BufReader};
|
||||||
|
use zip;
|
||||||
|
use tacview_splitter::lib;
|
||||||
|
use tacview_splitter::lib::WriteData;
|
||||||
|
|
||||||
|
const COMMENT: char = '#';
|
||||||
|
const MINUS: char = '-';
|
||||||
|
const EXTENSION_ZIP: &str = ".zip.acmi";
|
||||||
|
const EXTENSION_TXT: &str = ".txt.acmi";
|
||||||
|
|
||||||
|
const UNKNOWN: u8 = 0;
|
||||||
|
const TIMESTAMP: u8 = 1;
|
||||||
|
const DESTRUCTION: u8 = 2;
|
||||||
|
const TELEMETRY: u8 = 3;
|
||||||
|
|
||||||
|
const ERR_CANNOT_OPEN_OUTPUT: &str = "Could not open output file";
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let (input_filename, is_zip) = find_input_file();
|
||||||
|
println!("Processing {}", input_filename);
|
||||||
|
let lines = read_data(&input_filename, is_zip);
|
||||||
|
let (header, body) = split_into_header_and_body(lines);
|
||||||
|
let bodies_by_coalition = divide_body_by_coalition(&body);
|
||||||
|
|
||||||
|
let output_filenames = get_output_filenames(&input_filename);
|
||||||
|
if is_zip {
|
||||||
|
let mut descriptors = get_descriptors_zip(output_filenames);
|
||||||
|
descriptors.write(header, bodies_by_coalition)
|
||||||
|
} else {
|
||||||
|
let mut descriptors = get_descriptors_txt(output_filenames);
|
||||||
|
descriptors.write(header, bodies_by_coalition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn split_into_header_and_body(lines: Vec<String>) -> (Vec<String>, Vec<String>) {
|
||||||
|
let mut i=0;
|
||||||
|
for line in &lines {
|
||||||
|
if line.chars().nth(0).expect("malformed line") == COMMENT {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
return (lines[..i].to_vec(), lines[i..].to_vec());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn divide_body_by_coalition(body: &'static Vec<String>) -> lib::BodiesByCoalition<'static> {
|
||||||
|
let mut bbc = lib::BodiesByCoalition{blue: Vec::new(), red: Vec::new(), violet: Vec::new()};
|
||||||
|
let mut continued = false;
|
||||||
|
let mut line_type: u8 = UNKNOWN;
|
||||||
|
let mut ids = lib::IDs{blue: Vec::new(), red: Vec::new(), violet: Vec::new(), unknown: Vec::new()};
|
||||||
|
for line in body {
|
||||||
|
let result = process_line(continued, &mut ids, line, line_type);
|
||||||
|
line_type = result.0;
|
||||||
|
continued = result.1;
|
||||||
|
let id = result.2;
|
||||||
|
if line_type == TIMESTAMP {
|
||||||
|
bbc.blue.push(line);
|
||||||
|
bbc.red.push(line);
|
||||||
|
bbc.violet.push(line);
|
||||||
|
} else { // destruction or telemetry
|
||||||
|
if ids.blue.contains(&id) {
|
||||||
|
bbc.blue.push(line);
|
||||||
|
} else if ids.red.contains(&id) {
|
||||||
|
bbc.red.push(line);
|
||||||
|
} else if ids.violet.contains(&id) {
|
||||||
|
bbc.violet.push(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bbc
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_line<'a>(continued: bool, ids: &mut lib::IDs<'a>, line: &'a String, last_line_type: u8) -> (u8, bool, &'a str) {
|
||||||
|
let mut id = "both";
|
||||||
|
let line_type;
|
||||||
|
let will_continue: bool;
|
||||||
|
if !continued {
|
||||||
|
let first_char = line.chars().nth(0).expect("malformed line");
|
||||||
|
if first_char == COMMENT {
|
||||||
|
line_type = TIMESTAMP;
|
||||||
|
} else if first_char == MINUS {
|
||||||
|
line_type = DESTRUCTION;
|
||||||
|
} else {
|
||||||
|
line_type = TELEMETRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if line_type == TELEMETRY {
|
||||||
|
id = line
|
||||||
|
.split_once(',')
|
||||||
|
.unwrap()
|
||||||
|
.0;
|
||||||
|
//let id_str = id.to_string();
|
||||||
|
if line.contains("Color=") {
|
||||||
|
if line.contains("Color=Blue") {
|
||||||
|
ids.blue.push(id);
|
||||||
|
} else if line.contains("Color=Red") {
|
||||||
|
ids.red.push(id);
|
||||||
|
} else if line.contains("Color=Violet") {
|
||||||
|
ids.violet.push(id);
|
||||||
|
} else {
|
||||||
|
ids.unknown.push(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
line_type = last_line_type;
|
||||||
|
}
|
||||||
|
if line.ends_with("\\") {
|
||||||
|
will_continue = true;
|
||||||
|
} else {
|
||||||
|
will_continue = false;
|
||||||
|
}
|
||||||
|
(line_type, will_continue, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_output_filenames(input_filename: &String) -> lib::OutputFilenames {
|
||||||
|
let blue = input_filename.replace(".zip", "_blue.zip");
|
||||||
|
let red = input_filename.replace(".zip", "_red.zip");
|
||||||
|
let violet = input_filename.replace(".zip", "_violet.zip");
|
||||||
|
let output_filenames_zip = lib::FilenamesVariant{blue, red, violet};
|
||||||
|
|
||||||
|
let blue = input_filename.replace(".zip", "_blue.txt");
|
||||||
|
let red = input_filename.replace(".zip", "_red.txt");
|
||||||
|
let violet = input_filename.replace(".zip", "_violet.txt");
|
||||||
|
let output_filenames_txt = lib::FilenamesVariant{blue, red, violet};
|
||||||
|
|
||||||
|
let output_filenames = lib::OutputFilenames{txt: output_filenames_txt, zip: output_filenames_zip};
|
||||||
|
output_filenames
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_input_file() -> (String, bool) {
|
||||||
|
let read_dir = fs::read_dir(".").expect("Could not read current directory");
|
||||||
|
for entry_result in read_dir {
|
||||||
|
let entry = entry_result.expect("Could not parse DirEntry");
|
||||||
|
let path_buf = entry.path();
|
||||||
|
let filename = path_buf.to_string_lossy().to_string();
|
||||||
|
if filename.ends_with(EXTENSION_TXT) {
|
||||||
|
return (filename, false);
|
||||||
|
} else if filename.ends_with(EXTENSION_ZIP) {
|
||||||
|
return (filename, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
println!("No tacview input file found in current directory.");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn read_data(filename: &String, is_zip: bool) -> Vec<String> {
|
||||||
|
let file = fs::File::open(filename).expect("Could not read from input file");
|
||||||
|
let buf = BufReader::new(file);
|
||||||
|
return if is_zip {
|
||||||
|
let mut archive = zip::ZipArchive::new(buf).expect("Could not read zip data");
|
||||||
|
let inner_file = archive.by_index(0).unwrap();
|
||||||
|
let inner_buf = BufReader::new(inner_file);
|
||||||
|
let lines: Vec<String> = inner_buf.lines()
|
||||||
|
.map(|l| l.expect("Could not parse line"))
|
||||||
|
.collect();
|
||||||
|
lines
|
||||||
|
} else {
|
||||||
|
let lines: Vec<String> = buf.lines()
|
||||||
|
.map(|l| l.expect("Could not parse line"))
|
||||||
|
.collect();
|
||||||
|
lines
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_descriptors_zip(filenames: lib::OutputFilenames) -> lib::DescriptorsZip {
|
||||||
|
let options = zip::write::FileOptions::default().compression_method(zip::CompressionMethod::Deflated);
|
||||||
|
|
||||||
|
let file = fs::File::create(&filenames.zip.blue).expect(ERR_CANNOT_OPEN_OUTPUT);
|
||||||
|
let mut blue = zip::ZipWriter::new(file);
|
||||||
|
blue.start_file(&filenames.txt.blue, options).unwrap();
|
||||||
|
|
||||||
|
let file = fs::File::create(&filenames.zip.red).expect(ERR_CANNOT_OPEN_OUTPUT);
|
||||||
|
let mut red = zip::ZipWriter::new(file);
|
||||||
|
red.start_file(&filenames.txt.red, options).unwrap();
|
||||||
|
|
||||||
|
let file = fs::File::create(&filenames.zip.violet).expect(ERR_CANNOT_OPEN_OUTPUT);
|
||||||
|
let mut violet = zip::ZipWriter::new(file);
|
||||||
|
violet.start_file(&filenames.txt.violet, options).unwrap();
|
||||||
|
|
||||||
|
let descriptors = lib::DescriptorsZip{blue, red, violet};
|
||||||
|
descriptors
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_descriptors_txt(filenames: lib::OutputFilenames) -> lib::DescriptorsTxt {
|
||||||
|
let blue = fs::File::create(&filenames.txt.blue).expect(ERR_CANNOT_OPEN_OUTPUT);
|
||||||
|
let red = fs::File::create(&filenames.txt.red).expect(ERR_CANNOT_OPEN_OUTPUT);
|
||||||
|
let violet = fs::File::create(&filenames.txt.violet).expect(ERR_CANNOT_OPEN_OUTPUT);
|
||||||
|
let descriptors = lib::DescriptorsTxt{blue, red, violet};
|
||||||
|
descriptors
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user