mirror of
https://codeberg.org/scip/tablizer.git
synced 2025-12-17 20:41:03 +01:00
129 lines
3.2 KiB
Go
129 lines
3.2 KiB
Go
package zygo
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
|
|
"github.com/glycerine/greenpack/msgp"
|
|
)
|
|
|
|
// (bsave value path) writes value as greenpack to file.
|
|
//
|
|
// (greenpack value) writes value as greenpack to SexpRaw in memory.
|
|
//
|
|
// bsave converts to binary with (togo) then saves the binary to file.
|
|
func WriteShadowGreenpackToFileFunction(env *Zlisp, name string, args []Sexp) (Sexp, error) {
|
|
narg := len(args)
|
|
if narg < 1 || narg > 2 {
|
|
return SexpNull, WrongNargs
|
|
}
|
|
// check arg[0]
|
|
var asHash *SexpHash
|
|
switch x := args[0].(type) {
|
|
default:
|
|
return SexpNull, fmt.Errorf("%s error: top value must be a hash or defmap; we see '%T'", name, args[0])
|
|
case *SexpHash:
|
|
// okay, good
|
|
asHash = x
|
|
}
|
|
|
|
switch name {
|
|
case "bsave":
|
|
if narg != 2 {
|
|
return SexpNull, WrongNargs
|
|
}
|
|
|
|
case "greenpack":
|
|
if narg != 1 {
|
|
return SexpNull, WrongNargs
|
|
}
|
|
var buf bytes.Buffer
|
|
_, err := toGreenpackHelper(env, asHash, &buf, "memory")
|
|
if err != nil {
|
|
return SexpNull, err
|
|
}
|
|
return &SexpRaw{Val: buf.Bytes()}, nil
|
|
}
|
|
|
|
// check arg[1]
|
|
var fn string
|
|
switch fna := args[1].(type) {
|
|
case *SexpStr:
|
|
fn = fna.S
|
|
default:
|
|
return SexpNull, fmt.Errorf("error: %s requires a string (SexpStr) path to write to as the second argument. we got type %T / value = %v", name, args[1], args[1])
|
|
}
|
|
|
|
// don't overwrite existing file
|
|
if FileExists(fn) {
|
|
return SexpNull, fmt.Errorf("error: %s refusing to write to existing file '%s'",
|
|
name, fn)
|
|
}
|
|
|
|
f, err := os.Create(fn)
|
|
if err != nil {
|
|
return SexpNull, fmt.Errorf("error: %s sees error trying to create file '%s': '%v'", name, fn, err)
|
|
}
|
|
defer f.Close()
|
|
|
|
_, err = toGreenpackHelper(env, asHash, f, fn)
|
|
return SexpNull, err
|
|
}
|
|
|
|
func toGreenpackHelper(env *Zlisp, asHash *SexpHash, f io.Writer, fn string) (Sexp, error) {
|
|
|
|
// create shadow structs
|
|
_, err := ToGoFunction(env, "togo", []Sexp{asHash})
|
|
if err != nil {
|
|
return SexpNull, fmt.Errorf("ToGo call sees error: '%v'", err)
|
|
}
|
|
|
|
if asHash.GoShadowStruct == nil {
|
|
return SexpNull, fmt.Errorf("GoShadowStruct was nil, on attempt to write to '%s'", fn)
|
|
}
|
|
|
|
enc, ok := interface{}(asHash.GoShadowStruct).(msgp.Encodable)
|
|
if !ok {
|
|
return SexpNull, fmt.Errorf("error: GoShadowStruct was not greenpack Encodable -- run `go generate` or add greenpack to the source file for type '%T'. on attempt to save to '%s'", asHash.GoShadowStruct, fn)
|
|
}
|
|
w := msgp.NewWriter(f)
|
|
err = msgp.Encode(w, enc)
|
|
if err != nil {
|
|
return SexpNull, fmt.Errorf("error: greenpack encoding to file '%s' of type '%T' sees error '%v'", fn, asHash.GoShadowStruct, err)
|
|
}
|
|
err = w.Flush()
|
|
return SexpNull, err
|
|
}
|
|
|
|
func ReadGreenpackFromFileFunction(env *Zlisp, name string, args []Sexp) (Sexp, error) {
|
|
narg := len(args)
|
|
|
|
if narg != 1 {
|
|
return SexpNull, WrongNargs
|
|
}
|
|
var fn string
|
|
switch fna := args[0].(type) {
|
|
case *SexpStr:
|
|
fn = fna.S
|
|
default:
|
|
return SexpNull, fmt.Errorf("%s requires a string path to read. we got type %T / value = %v", name, args[0], args[0])
|
|
}
|
|
|
|
if !FileExists(string(fn)) {
|
|
return SexpNull, fmt.Errorf("file '%s' does not exist", fn)
|
|
}
|
|
f, err := os.Open(fn)
|
|
if err != nil {
|
|
return SexpNull, err
|
|
}
|
|
defer f.Close()
|
|
by, err := ioutil.ReadAll(f)
|
|
if err != nil {
|
|
return SexpNull, err
|
|
}
|
|
return MsgpackToSexp(by, env)
|
|
}
|