Skip to content

Commit

Permalink
Add fastrand and tempfile
Browse files Browse the repository at this point in the history
  • Loading branch information
gtrafimenkov committed Oct 22, 2023
1 parent cc3f2b2 commit 7ec69eb
Show file tree
Hide file tree
Showing 18 changed files with 1,351 additions and 34 deletions.
21 changes: 21 additions & 0 deletions examples/defer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Replacement for Go's defer.

use ggstd::compat::Defer;

fn main() {
println!("starting");
let msg = "hello".to_string();
let _d = Defer(|| println!("finishing 1: {}", msg));
{
let _d = Defer(|| println!("finishing 2"));
}
let _d = Defer(|| println!("finishing 3"));
println!("working");

// Output:
// starting
// finishing 2
// working
// finishing 3
// finishing 1: hello
}
13 changes: 13 additions & 0 deletions examples/tempfile.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use ggstd::os::TempDir;
use ggstd::os::TempFile;

fn main() {
let tf = TempFile::new("ggstd-*.txt").unwrap();
println!("{}", tf.path.to_string_lossy());

let td = TempDir::new("ggstd-").unwrap();
println!("{}", td.path.to_string_lossy());

let tf = TempFile::new_in_dir(&td.path, "ggstd-*.txt").unwrap();
println!("{}", tf.path.to_string_lossy());
}
36 changes: 36 additions & 0 deletions src/compat/defer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/// Defer allows to run a piece of code when a specific scope
/// is finished. It is somewhat similar to Go's defer statement,
/// but Go's defer runs at the function end, this Defer runs
/// at the scope exit.
///
/// Example:
/// let _d = Defer(|| println!("finishing 1"));
/// let _d = Defer(|| println!("finishing 2"));
pub struct Defer<F: Fn()>(pub F);

impl<F: Fn()> Drop for Defer<F> {
fn drop(&mut self) {
(self.0)();
}
}

/// DeferDirRemoval runs recursive directory removal when the
/// object goes out of the scope. Errors during removal are ignored.
///
/// Example:
/// let _d = DeferDirRemoval::new("/tmp/foo-bar-baz");
pub struct DeferDirRemoval<'a> {
path: &'a str,
}

impl<'a> DeferDirRemoval<'a> {
pub fn new(path: &'a str) -> Self {
Self { path }
}
}

impl<'a> Drop for DeferDirRemoval<'a> {
fn drop(&mut self) {
let _ = std::fs::remove_dir_all(self.path);
}
}
3 changes: 3 additions & 0 deletions src/compat/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ pub fn string(b: &[u8]) -> String {
}

pub mod chars;
mod defer;
pub mod readers;

pub use defer::{Defer, DeferDirRemoval};

#[cfg(test)]
mod readers_test;
16 changes: 8 additions & 8 deletions src/io/io_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,9 +499,9 @@ fn test_read_at_least_int(rb: &mut bytes::Buffer) {

// fn TestOffsetWriter_Seek() {
// tmpfilename := "TestOffsetWriter_Seek"
// tmpfile, err := os.CreateTemp(t.TempDir(), tmpfilename)
// tmpfile, err := os.create_temp(t.temp_dir(), tmpfilename)
// if err != nil || tmpfile == nil {
// t.Fatalf("CreateTemp(%s) failed: {}", tmpfilename, err)
// t.Fatalf("create_temp(%s) failed: {}", tmpfilename, err)
// }
// defer tmpfile.Close()
// w := NewOffsetWriter(tmpfile, 0)
Expand Down Expand Up @@ -559,16 +559,16 @@ fn test_read_at_least_int(rb: &mut bytes::Buffer) {
// fn TestOffsetWriter_WriteAt() {
// const content = "0123456789ABCDEF"
// contentSize := int64(len(content))
// tmpdir, err := os.MkdirTemp(t.TempDir(), "TestOffsetWriter_WriteAt")
// tmpdir, err := os.mkdir_temp(t.temp_dir(), "TestOffsetWriter_WriteAt")
// if err != nil {
// t.Fatal(err)
// }

// work := fn(off, at int64) {
// position := fmt.Sprintf("off_%d_at_{}", off, at)
// tmpfile, err := os.CreateTemp(tmpdir, position)
// tmpfile, err := os.create_temp(tmpdir, position)
// if err != nil || tmpfile == nil {
// t.Fatalf("CreateTemp(%s) failed: {}", position, err)
// t.Fatalf("create_temp(%s) failed: {}", position, err)
// }
// defer tmpfile.Close()

Expand Down Expand Up @@ -612,13 +612,13 @@ fn test_read_at_least_int(rb: &mut bytes::Buffer) {
// fn TestOffsetWriter_Write() {
// const content = "0123456789ABCDEF"
// contentSize := len(content)
// tmpdir := t.TempDir()
// tmpdir := t.temp_dir()

// makeOffsetWriter := fn(name string) (*OffsetWriter, *os.File) {
// tmpfilename := "TestOffsetWriter_Write_" + name
// tmpfile, err := os.CreateTemp(tmpdir, tmpfilename)
// tmpfile, err := os.create_temp(tmpdir, tmpfilename)
// if err != nil || tmpfile == nil {
// t.Fatalf("CreateTemp(%s) failed: {}", tmpfilename, err)
// t.Fatalf("create_temp(%s) failed: {}", tmpfilename, err)
// }
// return NewOffsetWriter(tmpfile, 0), tmpfile
// }
Expand Down
265 changes: 265 additions & 0 deletions src/os/example_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
// // Copyright 2016 The Go Authors. All rights reserved.
// // Use of this source code is governed by a BSD-style
// // license that can be found in the LICENSE file.

// package os_test

// import (
// "errors"
// "fmt"
// "io/fs"
// "log"
// "os"
// "path/filepath"
// "time"
// )

// func ExampleOpenFile() {
// f, err := os.OpenFile("notes.txt", os.O_RDWR|os.O_CREATE, 0755)
// if err != nil {
// log.Fatal(err)
// }
// if err := f.Close(); err != nil {
// log.Fatal(err)
// }
// }

// func ExampleOpenFile_append() {
// // If the file doesn't exist, create it, or append to the file
// f, err := os.OpenFile("access.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
// if err != nil {
// log.Fatal(err)
// }
// if _, err := f.Write([]byte("appended some data\n")); err != nil {
// f.Close() // ignore error; Write error takes precedence
// log.Fatal(err)
// }
// if err := f.Close(); err != nil {
// log.Fatal(err)
// }
// }

// func ExampleChmod() {
// if err := os.Chmod("some-filename", 0644); err != nil {
// log.Fatal(err)
// }
// }

// func ExampleChtimes() {
// mtime := time.Date(2006, time.February, 1, 3, 4, 5, 0, time.UTC)
// atime := time.Date(2007, time.March, 2, 4, 5, 6, 0, time.UTC)
// if err := os.Chtimes("some-filename", atime, mtime); err != nil {
// log.Fatal(err)
// }
// }

// func ExampleFileMode() {
// fi, err := os.Lstat("some-filename")
// if err != nil {
// log.Fatal(err)
// }

// fmt.Printf("permissions: %#o\n", fi.Mode().Perm()) // 0400, 0777, etc.
// switch mode := fi.Mode(); {
// case mode.IsRegular():
// fmt.Println("regular file")
// case mode.IsDir():
// fmt.Println("directory")
// case mode&fs.ModeSymlink != 0:
// fmt.Println("symbolic link")
// case mode&fs.ModeNamedPipe != 0:
// fmt.Println("named pipe")
// }
// }

// func ExampleErrNotExist() {
// filename := "a-nonexistent-file"
// if _, err := os.Stat(filename); errors.Is(err, fs.ErrNotExist) {
// fmt.Println("file does not exist")
// }
// // Output:
// // file does not exist
// }

// func ExampleExpand() {
// mapper := func(placeholderName string) string {
// switch placeholderName {
// case "DAY_PART":
// return "morning"
// case "NAME":
// return "Gopher"
// }

// return ""
// }

// fmt.Println(os.Expand("Good ${DAY_PART}, $NAME!", mapper))

// // Output:
// // Good morning, Gopher!
// }

// func ExampleExpandEnv() {
// os.Setenv("NAME", "gopher")
// os.Setenv("BURROW", "/usr/gopher")

// fmt.Println(os.ExpandEnv("$NAME lives in ${BURROW}."))

// // Output:
// // gopher lives in /usr/gopher.
// }

// func ExampleLookupEnv() {
// show := func(key string) {
// val, ok := os.LookupEnv(key)
// if !ok {
// fmt.Printf("%s not set\n", key)
// } else {
// fmt.Printf("%s=%s\n", key, val)
// }
// }

// os.Setenv("SOME_KEY", "value")
// os.Setenv("EMPTY_KEY", "")

// show("SOME_KEY")
// show("EMPTY_KEY")
// show("MISSING_KEY")

// // Output:
// // SOME_KEY=value
// // EMPTY_KEY=
// // MISSING_KEY not set
// }

// func ExampleGetenv() {
// os.Setenv("NAME", "gopher")
// os.Setenv("BURROW", "/usr/gopher")

// fmt.Printf("%s lives in %s.\n", os.Getenv("NAME"), os.Getenv("BURROW"))

// // Output:
// // gopher lives in /usr/gopher.
// }

// func ExampleUnsetenv() {
// os.Setenv("TMPDIR", "/my/tmp")
// defer os.Unsetenv("TMPDIR")
// }

// func ExampleReadDir() {
// files, err := os.ReadDir(".")
// if err != nil {
// log.Fatal(err)
// }

// for _, file := range files {
// fmt.Println(file.Name())
// }
// }

// func ExampleMkdirTemp() {
// dir, err := os.mkdir_temp("", "example")
// if err != nil {
// log.Fatal(err)
// }
// defer os.RemoveAll(dir) // clean up

// file := filepath.Join(dir, "tmpfile")
// if err := os.WriteFile(file, []byte("content"), 0666); err != nil {
// log.Fatal(err)
// }
// }

// func ExampleMkdirTemp_suffix() {
// logsDir, err := os.mkdir_temp("", "*-logs")
// if err != nil {
// log.Fatal(err)
// }
// defer os.RemoveAll(logsDir) // clean up

// // Logs can be cleaned out earlier if needed by searching
// // for all directories whose suffix ends in *-logs.
// globPattern := filepath.Join(os.temp_dir(), "*-logs")
// matches, err := filepath.Glob(globPattern)
// if err != nil {
// log.Fatalf("Failed to match %q: %v", globPattern, err)
// }

// for _, match := range matches {
// if err := os.RemoveAll(match); err != nil {
// log.Printf("Failed to remove %q: %v", match, err)
// }
// }
// }

// func ExampleCreateTemp() {
// f, err := os.create_temp("", "example")
// if err != nil {
// log.Fatal(err)
// }
// defer os.Remove(f.Name()) // clean up

// if _, err := f.Write([]byte("content")); err != nil {
// log.Fatal(err)
// }
// if err := f.Close(); err != nil {
// log.Fatal(err)
// }
// }

// func ExampleCreateTemp_suffix() {
// f, err := os.create_temp("", "example.*.txt")
// if err != nil {
// log.Fatal(err)
// }
// defer os.Remove(f.Name()) // clean up

// if _, err := f.Write([]byte("content")); err != nil {
// f.Close()
// log.Fatal(err)
// }
// if err := f.Close(); err != nil {
// log.Fatal(err)
// }
// }

// func ExampleReadFile() {
// data, err := os.ReadFile("testdata/hello")
// if err != nil {
// log.Fatal(err)
// }
// os.Stdout.Write(data)

// // Output:
// // Hello, Gophers!
// }

// func ExampleWriteFile() {
// err := os.WriteFile("testdata/hello", []byte("Hello, Gophers!"), 0666)
// if err != nil {
// log.Fatal(err)
// }
// }

// func ExampleMkdir() {
// err := os.Mkdir("testdir", 0750)
// if err != nil && !os.IsExist(err) {
// log.Fatal(err)
// }
// err = os.WriteFile("testdir/testfile.txt", []byte("Hello, Gophers!"), 0660)
// if err != nil {
// log.Fatal(err)
// }
// }

// func ExampleMkdirAll() {
// err := os.MkdirAll("test/subdir", 0750)
// if err != nil && !os.IsExist(err) {
// log.Fatal(err)
// }
// err = os.WriteFile("test/subdir/testfile.txt", []byte("Hello, Gophers!"), 0660)
// if err != nil {
// log.Fatal(err)
// }
// }
Loading

0 comments on commit 7ec69eb

Please sign in to comment.