Basic Usage

Simply define a proc that takes in parameters with fields (aka "sources") and outputs a object/ref object/named tuple value. Then annotate it with the {.map.} pragma and you're done.

Note though that parameters without fields (e.g. int, string etc.) will not get auto assigned to specific field. They should only be used to perform manual assignments in the proc body.

import std/times
import mapster

type A1 = object
  str: string
  num: int
  floatNum: float
  dateTime: DateTime
  boolean: bool

type B1 = object
  str: string
  num: int
  floatNum: float
  dateTime: DateTime
  boolean: bool

let a1 = A1(
  str: "str",
  num: 5,
  floatNum: 2.5,
  dateTime: now(),
  boolean: true
)

proc myMapProc(x: A1): B1 {.map.} = discard

let myB1: B1 = myMapProc(a1)
let expected1: B1 = B1(str: "str", num: 5, floatNum: 2.5, dateTime: a1.dateTime, boolean: true)
doAssert myB1 == expected1

Mapping with custom logic

Sometimes you may need additional logic, double an int, concatenate strings, assign to a field where the names don't match or the like. You can simply write those custom assignments in the body of your map proc!

Treat it as if it were a normal procedure that has invisible assignmen statements at the beginning!

type A2 = object
  str: string
  num: int

type B2 = object
  str: string
  num: int
  doubleNum: int
  constNum: int

let a2 = A2(
  str: "str",
  num: 5
)

proc myMapProc(x: A2): B2 {.map.} =
  result.doubleNum = x.num * 2
  result.constNum = 20

let myB2: B2 = myMapProc(a2)
let expectedB2: B2 = B2(str: "str", num: 5, doubleNum: 10, constNum: 20)
doAssert myB2 == expectedB2

Mapping with object variant sources

Generally mapster will try to map fields from an object variant parameter if they're available. However, if an object variant of a given kind used for mapping is missing a field, it will remain default initialized on the result.

It is generally better to write custom assignment statements within the map-proc when it comes to object-variant parameters.

type Kind = enum
  A, B
type A3 = object
  case kind: Kind
  of A: str: string
  of B: num: int

type B3 = object
  kind: Kind
  str: string

let a31 = A3(str: "str", kind: Kind.A)
let a32 = A3(num: 5, kind: Kind.B)

proc myMapProc(x: A3): B3 {.map.} = discard

let myB31: B3 = myMapProc(a31)
let myB32: B3 = myMapProc(a32)
let expectedB31: B3 = B3(kind: Kind.A, str: "str")
let expectedB32: B3 = B3(kind: Kind.B, str: "")

doAssert myB31 == expectedB31
doAssert myB32 == expectedB32