github.com/coyove/nj@v0.0.0-20221110084952-c7f8db1065c3/bas/io.go (about)

     1  package bas
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"fmt"
     7  	"io"
     8  	"strings"
     9  
    10  	"github.com/coyove/nj/typ"
    11  )
    12  
    13  type valueIO Value
    14  
    15  // Reader creates an io.Reader from value, Read() may fail if value doesn't support reading.
    16  func (v Value) Reader() io.Reader {
    17  	switch rd := v.Interface().(type) {
    18  	case io.Reader:
    19  		return rd
    20  	case []byte:
    21  		return bytes.NewReader(rd)
    22  	case string:
    23  		return strings.NewReader(v.Str())
    24  	}
    25  	return valueIO(v)
    26  }
    27  
    28  // Writer creates an io.Writer from value, Write() may fail if value doesn't support writing.
    29  func (v Value) Writer() io.Writer {
    30  	switch rd := v.Interface().(type) {
    31  	case io.Writer:
    32  		return rd
    33  	case []byte:
    34  		w := bytes.NewBuffer(rd)
    35  		w.Reset()
    36  		return w
    37  	}
    38  	return valueIO(v)
    39  }
    40  
    41  // Closer creates an io.Closer from value, Close() may fail if value doesn't support closing.
    42  func (v Value) Closer() io.Closer {
    43  	if rd, ok := v.Interface().(io.Closer); ok {
    44  		return rd
    45  	}
    46  	return valueIO(v)
    47  }
    48  
    49  func (m valueIO) Read(p []byte) (int, error) {
    50  	switch Value(m).Type() {
    51  	case typ.Native:
    52  		if rd, _ := Value(m).Interface().(io.Reader); rd != nil {
    53  			return rd.Read(p)
    54  		}
    55  	case typ.Object:
    56  		if rb := Value(m).Object().Get(Str("read2")); rb.IsObject() {
    57  			t := rb.Object().Call(nil, Bytes(p)).AssertShape("(i, EN)", "Reader.read2").Native()
    58  			if t.Get(1).IsError() {
    59  				return t.Get(0).Int(), t.Get(1).Error()
    60  			}
    61  			return t.Get(0).Int(), nil
    62  		}
    63  		if rb := Value(m).Object().Get(Str("read")); rb.IsObject() {
    64  			switch v := rb.Object().Call(nil, Int(len(p))); v.Type() {
    65  			case typ.Nil:
    66  				return 0, io.EOF
    67  			case typ.String:
    68  				return copy(p, v.Str()), nil
    69  			case typ.Native:
    70  				return copy(p, v.AssertShape("sB", "Reader.read").Native().Unwrap().([]byte)), nil
    71  			default:
    72  				v.AssertShape("sB", "Reader.read")
    73  			}
    74  		}
    75  	}
    76  	return 0, fmt.Errorf("reader not implemented")
    77  }
    78  
    79  func (m valueIO) WriteString(p string) (int, error) {
    80  	return m.Write([]byte(p))
    81  }
    82  
    83  func (m valueIO) Write(p []byte) (int, error) {
    84  	switch Value(m).Type() {
    85  	case typ.Native:
    86  		if rd, _ := Value(m).Interface().(io.Writer); rd != nil {
    87  			return rd.Write(p)
    88  		}
    89  	case typ.Object:
    90  		if rb := Value(m).Object().Get(Str("write")); rb.IsObject() {
    91  			v := rb.Object().Call(nil, Bytes(p))
    92  			if v.IsError() {
    93  				return 0, v.Error()
    94  			}
    95  			return v.AssertNumber("Writer.write").Int(), nil
    96  		}
    97  		if rb := Value(m).Object().Get(Str("write2")); rb.IsObject() {
    98  			t := rb.Object().Call(nil, Bytes(p)).AssertShape("(i, EN)", "Writer.write2").Native()
    99  			if t.Get(1).IsError() {
   100  				return t.Get(0).Int(), t.Get(1).Error()
   101  			}
   102  			return t.Get(0).Int(), nil
   103  		}
   104  	}
   105  	return 0, fmt.Errorf("writer not implemented")
   106  }
   107  
   108  func (m valueIO) Close() error {
   109  	switch Value(m).Type() {
   110  	case typ.Native:
   111  		if rd, _ := Value(m).Interface().(io.Closer); rd != nil {
   112  			return rd.Close()
   113  		}
   114  	case typ.Object:
   115  		if rb := Value(m).Object().Get(Str("close")); rb.IsObject() {
   116  			if v := rb.Object().Call(nil); v.IsError() {
   117  				return v.Error()
   118  			}
   119  			return nil
   120  		}
   121  	}
   122  	return fmt.Errorf("closer not implemented")
   123  }
   124  
   125  type ioReadlinesStruct struct {
   126  	rd    *bufio.Reader
   127  	delim byte
   128  	bytes bool
   129  }