d3nmas3n0 1 an în urmă
părinte
comite
c51025c691
5 a modificat fișierele cu 137 adăugiri și 4 ștergeri
  1. 13 0
      codex.go
  2. 64 0
      codex_bitmap.go
  3. 28 2
      codex_lvar.go
  4. 16 0
      codex_string.go
  5. 16 2
      codex_test.go

+ 13 - 0
codex.go

@@ -11,6 +11,8 @@ type Codex interface {
 
   ID() string
   Decode(data []byte, pos int, value interface{}) (int, error)
+
+  Encode(data []byte, pos int, value interface{}) (int, error)
 }
 
 type CodexStruct struct {
@@ -91,3 +93,14 @@ func (c *CodexStruct) Decode(data []byte, pos int, value interface{}) (int, erro
   return ppos, nil
 }
 
+func (c *CodexStruct) Encode(data []byte, pos int, value interface{}) (int, error) {
+  ppos := pos
+  var err error
+  for _, f := range c.fields {
+    ppos, err = f.Encode(data, ppos, value)
+    if err != nil {
+      return pos, err
+    }
+  }
+  return ppos, nil
+}

+ 64 - 0
codex_bitmap.go

@@ -83,3 +83,67 @@ func (c *CodexBitmap) Decode(data []byte, pos int, value interface{}) (int, erro
   }
   return ppos, nil
 }
+
+func (c *CodexBitmap) Encode(data []byte, pos int, value interface{}) (int, error) {
+  if vm, ok := value.(map[string]interface{}); ok {
+    ppos := pos
+    var bitmap [128]bool
+    for i, f := range c.fields {
+      bitmap[i+1] = vm[f.ID()] != nil
+    }
+    for i := 64; i<128; i++ {
+      if bitmap[i] {
+        bitmap[0] = true
+        break
+      }
+    }
+    bi := 0
+    for i := 0; i<16; i++ {
+      b := byte(0)
+      ba := byte(8)
+      for j := 1; j <= 4; j++ {
+        if bitmap[bi] {
+          b |= ba
+        }
+        ba >>= 1
+        bi += 1
+      }
+      if b > 9 {
+        data[ppos] = 38 + b
+      } else {
+        data[ppos] = 48 + b
+      }
+      ppos +=1
+    }
+    if bitmap[0] {
+      for i := 0; i<16; i++ {
+        b := byte(0)
+        ba := byte(8)
+        for j := 1; j <= 4; j++ {
+          if bitmap[bi] {
+            b |= ba
+          }
+          ba >>= 1
+          bi += 1
+        }
+        if b > 9 {
+          data[ppos] = 38 + b
+        } else {
+          data[ppos] = 48 + b
+        }
+        ppos +=1
+      }
+    }
+    var err error
+    for i, f := range c.fields {
+      if bitmap[i+1] {
+        ppos, err = f.Encode(data, ppos, value)
+        if err != nil {
+          return pos, err
+        }
+      }
+    }
+    return ppos, nil
+  }
+  panic(fmt.Sprintf("Invalid value type [%s] %+v", c.id, value))
+}

+ 28 - 2
codex_lvar.go

@@ -2,12 +2,15 @@ package codex
 
 import (
   "fmt"
+  "math"
   "strconv"
 )
 
 type CodexLVar struct {
-  id           string
-  PacketLength int
+  id            string
+  PacketLength  int
+  maxLength     int
+  lfmt          string
   length        int
 }
 
@@ -24,6 +27,8 @@ func (c *CodexLVar) init(cfg map[string]interface{}) {
   } else {
     panic(fmt.Sprintf("Invalid CodexLVar.Length %+v", cfg))
   }
+  c.maxLength = int(math.Pow(10, float64(c.PacketLength))) - 1
+  c.lfmt = fmt.Sprintf("%%0%dd", c.PacketLength)
 }
 
 func (c *CodexLVar) ID() string {
@@ -58,3 +63,24 @@ func (c *CodexLVar) Decode(data []byte, pos int, value interface{}) (int, error)
   }
   panic(fmt.Sprintf("Invalid value type %+v", value))
 }
+
+func (c *CodexLVar) Encode(data []byte, pos int, value interface{}) (int, error) {
+  if vm, ok := value.(map[string]interface{}); ok {
+    if v, ok := vm[c.id].(string); ok {
+      ppos := pos + c.PacketLength
+      lv := len(v)
+      if lv > c.maxLength {
+        sl := fmt.Sprintf(c.lfmt, c.maxLength)
+        copy(data[pos:ppos], []byte(sl))
+        copy(data[ppos:ppos+c.maxLength], []byte(v[0:c.maxLength]))
+        return ppos + c.maxLength, nil
+      }
+      sl := fmt.Sprintf(c.lfmt, lv)
+      copy(data[pos:ppos], []byte(sl))
+      copy(data[ppos:ppos+lv], []byte(v))
+      return ppos + lv, nil
+    }
+    panic(fmt.Sprintf("Invalid value type [%s] %+v", c.id, vm))
+  }
+  panic(fmt.Sprintf("Invalid value type [%s] %+v", c.id, value))
+}

+ 16 - 0
codex_string.go

@@ -44,3 +44,19 @@ func (c *CodexString) Decode(data []byte, pos int, value interface{}) (int, erro
   }
   panic(fmt.Sprintf("Invalid value type %+v", value))
 }
+
+func (c *CodexString) Encode(data []byte, pos int, value interface{}) (int, error) {
+  if vm, ok := value.(map[string]interface{}); ok {
+    if v, ok := vm[c.id].(string); ok {
+      lv := len(v)
+      if lv > c.length {
+        copy(data[pos:pos+lv], []byte(v[0:c.length]))
+        return pos + c.length, nil
+      }
+      copy(data[pos:pos+lv], []byte(v))
+      return pos + c.length, nil
+    }
+    panic(fmt.Sprintf("Invalid value type [%s] %+v", c.id, vm))
+  }
+  panic(fmt.Sprintf("Invalid value type [%s] %+v", c.id, value))
+}

+ 16 - 2
codex_test.go

@@ -7,7 +7,6 @@ import (
 
 func Test_iso8583_decode(t *testing.T) {
   codex := LoadCodex("iso8583.yaml")
-  t.Logf("Config: %v", codex)
   msg := "0800822000000000000004000000000000020623135417005592001005REQ 1"
   data := make(map[string]interface{})
   pos, err := codex.Decode([]byte(msg), 0, data)
@@ -23,4 +22,19 @@ func Test_iso8583_decode(t *testing.T) {
   assert.Equal(t, result, data, "decode data")
 }
 
-
+func Test_iso8583_encode(t *testing.T) {
+  codex := LoadCodex("iso8583.yaml")
+  data := map[string]interface{}{
+    "F000": "0800",
+    "F007": "0623135417",
+    "F011": "005592",
+    "F070": "001",
+    "F127": "REQ 1",
+  }
+  msg := make([]byte, 1024)
+  pos, err := codex.Encode(msg, 0, data)
+  assert.Nil(t, err, "encode err")
+  assert.Equal(t, 63, pos, "encode pos")
+  result := "0800822000000000000004000000000000020623135417005592001005REQ 1"
+  assert.Equal(t, result, string(msg[0:pos]), "encode data")
+}