mirror of
				https://github.com/therootcompany/golib.git
				synced 2025-10-30 20:52:53 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			227 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			227 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # Transform
 | |
| 
 | |
| [](https://pkg.go.dev/github.com/therootcompany/golib/3p/transform)
 | |
| 
 | |
| Transform is a Go package that provides a simple pattern for performing [chainable](#chaining) data transformations on streams of bytes. It conforms to the [io.Reader](https://golang.org/pkg/io/#Reader) interface and is useful for operations such as converting data formats, audio/video resampling, image transforms, log filters, regex line matching, etc.
 | |
| 
 | |
| The [transutil package](#transutil-package) provides few examples that work with JSON such as `JSONToMsgPack`, `MsgPackToJSON`, `JSONToPrettyJSON`, `JSONToUglyJSON`, `JSONToProtoBuf`, and `ProtoBufToJSON`. It also includes a handy `Gzipper` and `Gunzipper`.
 | |
| 
 | |
| # Getting Started
 | |
| 
 | |
| ## Installing
 | |
| 
 | |
| To start using Transform, install Go and run `go get`:
 | |
| 
 | |
| ```sh
 | |
| go get -u github.com/therootcompany/golib/3p/transform
 | |
| ```
 | |
| 
 | |
| ## Using
 | |
| 
 | |
| Below are a few very simple examples of custom transformers.
 | |
| 
 | |
| ### ToUpper
 | |
| 
 | |
| Convert a string to uppper case. Unicode aware. In this example
 | |
| we only process one rune at a time.
 | |
| 
 | |
| ```go
 | |
| func ToUpper(r io.Reader) io.Reader {
 | |
|    br := bufio.NewReader(r)
 | |
|    return transform.NewTransformer(func() ([]byte, error) {
 | |
|       c, _, err := br.ReadRune()
 | |
|       if err != nil {
 | |
|          return nil, err
 | |
|       }
 | |
|       return []byte(strings.ToUpper(string([]rune{c}))), nil
 | |
|    })
 | |
| }
 | |
| ```
 | |
| 
 | |
| ```go
 | |
| msg := "Hello World"
 | |
| data, err := ioutil.ReadAll(ToUpper(bytes.NewBufferString(msg)))
 | |
| if err != nil {
 | |
|    log.Fatal(err)
 | |
| }
 | |
| fmt.Println(string(data))
 | |
| ```
 | |
| 
 | |
| Output:
 | |
| 
 | |
| ```text
 | |
| HELLO WORLD
 | |
| ```
 | |
| 
 | |
| ### Rot13
 | |
| 
 | |
| The [Rot13](https://en.wikipedia.org/wiki/ROT13) cipher.
 | |
| 
 | |
| ```go
 | |
| func Rot13(r io.Reader) io.Reader {
 | |
|    buf := make([]byte, 256)
 | |
|    return transform.NewTransformer(func() ([]byte, error) {
 | |
|       n, err := r.Read(buf)
 | |
|       if err != nil {
 | |
|          return nil, err
 | |
|       }
 | |
|       for i := 0; i < n; i++ {
 | |
|          if buf[i] >= 'a' && buf[i] <= 'z' {
 | |
|             buf[i] = ((buf[i] - 'a' + 13) % 26) + 'a'
 | |
|          } else if buf[i] >= 'A' && buf[i] <= 'Z' {
 | |
|             buf[i] = ((buf[i] - 'A' + 13) % 26) + 'A'
 | |
|          }
 | |
|       }
 | |
|       return buf[:n], nil
 | |
|    })
 | |
| }
 | |
| ```
 | |
| 
 | |
| ```go
 | |
| msg := "Hello World"
 | |
| data, err := ioutil.ReadAll(Rot13(bytes.NewBufferString(msg)))
 | |
| if err != nil {
 | |
|    log.Fatal(err)
 | |
| }
 | |
| fmt.Println(string(data))
 | |
| ```
 | |
| 
 | |
| Output:
 | |
| 
 | |
| ```text
 | |
| Uryyb Jbeyq
 | |
| ```
 | |
| 
 | |
| ### RegExp Line Matcher
 | |
| 
 | |
| A line reader that filters lines that match on a RegExp pattern.
 | |
| 
 | |
| ```go
 | |
| func LineMatch(r io.Reader, pattern string) io.Reader {
 | |
|    br := bufio.NewReader(r)
 | |
|    return NewTransformer(func() ([]byte, error) {
 | |
|       for {
 | |
|          line, err := br.ReadBytes('\n')
 | |
|          matched, _ := regexp.Match(pattern, line)
 | |
|          if matched {
 | |
|             return line, err
 | |
|          }
 | |
|          if err != nil {
 | |
|             return nil, err
 | |
|          }
 | |
|       }
 | |
|    })
 | |
| }
 | |
| ```
 | |
| 
 | |
| ```go
 | |
| logs := `
 | |
| 23 Apr 17:32:23.604 [INFO] DB loaded in 0.551 seconds
 | |
| 23 Apr 17:32:23.605 [WARN] Disk space is low
 | |
| 23 Apr 17:32:23.054 [INFO] Server started on port 7812
 | |
| 23 Apr 17:32:23.141 [INFO] Ready for connections
 | |
| `
 | |
| data, err := ioutil.ReadAll(LineMatch(bytes.NewBufferString(logs), "WARN"))
 | |
| if err != nil {
 | |
|    log.Fatal(err)
 | |
| }
 | |
| fmt.Println(string(data))
 | |
| ```
 | |
| 
 | |
| Output:
 | |
| 
 | |
| ```text
 | |
| 23 Apr 17:32:23.605 [WARN] Disk space is low
 | |
| ```
 | |
| 
 | |
| ### LineTrimSpace
 | |
| 
 | |
| A line reader that trims the spaces from all lines.
 | |
| 
 | |
| ```go
 | |
| func LineTrimSpace(r io.Reader, pattern string) io.Reader {
 | |
|    br := bufio.NewReader(r)
 | |
|    return transform.NewTransformer(func() ([]byte, error) {
 | |
|       for {
 | |
|          line, err := br.ReadBytes('\n')
 | |
|          if len(line) > 0 {
 | |
|             line = append(bytes.TrimSpace(line), '\n')
 | |
|          }
 | |
|          return line, err
 | |
|       }
 | |
|    })
 | |
| }
 | |
| ```
 | |
| 
 | |
| ```go
 | |
| phrases := "  lacy timber \n"
 | |
| phrases += "\t\thybrid gossiping\t\n"
 | |
| phrases += " coy radioactivity\n"
 | |
| phrases += "rocky arrow  \n"
 | |
| out, err := ioutil.ReadAll(LineTrimSpace(bytes.NewBufferString(phrases)))
 | |
| if err != nil {
 | |
|    log.Fatal(err)
 | |
| }
 | |
| fmt.Printf("%s\n", out)
 | |
| ```
 | |
| 
 | |
| Output:
 | |
| 
 | |
| ```text
 | |
| lacy timber
 | |
| hybrid gossiping
 | |
| coy radioactivity
 | |
| rocky arrow
 | |
| ```
 | |
| 
 | |
| ### Chaining
 | |
| 
 | |
| A reader that matches lines on the letter 'o', trims the
 | |
| space from the lines, and transforms everything to upper case.
 | |
| 
 | |
| ```go
 | |
| phrases := "  lacy timber \n"
 | |
| phrases += "\t\thybrid gossiping\t\n"
 | |
| phrases += " coy radioactivity\n"
 | |
| phrases += "rocky arrow  \n"
 | |
| 
 | |
| r := ToUpper(LineTrimSpace(LineMatch(bytes.NewBufferString(phrases), "o")))
 | |
| 
 | |
| // Pass the string though the transformer.
 | |
| out, err := ioutil.ReadAll(r)
 | |
| if err != nil {
 | |
|    log.Fatal(err)
 | |
| }
 | |
| 
 | |
| fmt.Printf("%s\n", out)
 | |
| ```
 | |
| 
 | |
| Output:
 | |
| 
 | |
| ```text
 | |
| HYBRID GOSSIPING
 | |
| COY RADIOACTIVITY
 | |
| ROCKY ARROW
 | |
| ```
 | |
| 
 | |
| ## Transutil package
 | |
| 
 | |
| [](https://pkg.go.dev/github.com/tidwall/transform/transutil)
 | |
| 
 | |
| The `github.com/tidwall/transform/transutil` package includes additional examples.
 | |
| 
 | |
| ```go
 | |
| func Gunzipper(r io.Reader) io.Reader
 | |
| func Gzipper(r io.Reader) io.Reader
 | |
| func JSONToMsgPack(r io.Reader) io.Reader
 | |
| func JSONToPrettyJSON(r io.Reader) io.Reader
 | |
| func JSONToProtoBuf(r io.Reader, pb proto.Message, multimessage bool) io.Reader
 | |
| func JSONToUglyJSON(r io.Reader) io.Reader
 | |
| func MsgPackToJSON(r io.Reader) io.Reader
 | |
| func ProtoBufToJSON(r io.Reader, pb proto.Message, multimessage bool) io.Reader
 | |
| ```
 | |
| 
 | |
| ## License
 | |
| 
 | |
| This is a maintenance fork of <https://github.com/tidwall/transform>.
 |