blob: 9e81c0362c7fba44f5371619a4bc3d563c1fe97f [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
use std::collections::HashSet;
use std::ffi::CStr;
use std::io::{BufRead, BufReader, Write};
use std::os::raw::{c_char, c_int};
use teaclave_context::TeaclaveContextFile;
#[no_mangle]
pub extern "C" fn entrypoint(argc: c_int, argv: *const *const c_char) -> i32 {
assert_eq!(argc, 8);
// convert `argv` to `Vec<str>`
let argv: Vec<_> = (0..argc)
.map(|i| unsafe { CStr::from_ptr(*argv.add(i as usize)).to_string_lossy() })
.collect();
// Arguments are referenced in ODD indices
return run(
argv[1].as_ref(),
argv[3].as_ref(),
argv[5].as_ref(),
argv[7].as_ref(),
)
.unwrap();
}
/// This function take two input Teaclave file IDs and two output Teaclave file IDs,
/// and write identical result, the set intersection of two input files.
/// Each line of the input file will be regarded as a data entry.
/// There should be NO duplicate entries in each input file
fn run(
input_id1: &str,
input_id2: &str,
output_id1: &str,
output_id2: &str,
) -> Result<i32, std::io::Error> {
// Create TeaclaveContextFile from file IDs
let input1 = TeaclaveContextFile::open_input(input_id1)?;
let input2 = TeaclaveContextFile::open_input(input_id2)?;
let mut output1 = TeaclaveContextFile::create_output(output_id1)?;
let mut output2 = TeaclaveContextFile::create_output(output_id2)?;
// use HashSet to store it
let mut output_set: HashSet<String> = HashSet::new();
let reader1 = BufReader::new(input1);
let mut input_set1: HashSet<String> = HashSet::new();
// read from the first input file and save each data entry to the HashSet
reader1
.lines()
.map(|l| input_set1.insert(l.unwrap()))
.for_each(drop);
// read from the second input file and insert to output set if the data entry
// is also found in the first input file
let reader2 = BufReader::new(input2);
for line in reader2.lines() {
if let Ok(s) = line {
if input_set1.contains(&s) {
output_set.insert(s);
}
}
}
let intersection_size = output_set.len();
// write to both output files line by line
output_set
.iter()
.map(|l| {
write!(output1, "{}\n", l).unwrap();
write!(output2, "{}\n", l).unwrap();
})
.for_each(drop);
write!(output1, "done\n").unwrap();
write!(output2, "done\n").unwrap();
return Ok(intersection_size as _);
}