public function save($object, $meta=null)
    {
        if ($meta) {
            $meta = !$meta instanceof Meta ? $this->mapper->getMeta($meta) : $meta;
        } else {
            $meta = $this->mapper->getMeta(get_class($object));
        }

        if (!$meta->primary) {
            throw new Exception("No primary key for {$meta->id}");
        }

        $shouldInsert = null;
        $prival = null;
        if ($meta->autoinc) {
            $prival = $meta->getValue($object, $meta->autoinc);
            $shouldInsert = !$prival;
        } else {
            $prival = $meta->getIndexValue($object);
        }

        event_before: {
            if (isset($meta->on['beforeSave'])) {
                foreach ($meta->on['beforeSave'] as $cb) { $cb = [$object, $cb]; $cb(); }
            }
            if (isset($this->on['beforeSave'])) {
                foreach ($this->on['beforeSave'] as $cb) { $cb($object, $meta); }
            }
        }

        if ($shouldInsert === null) {
            $newpri = $meta->getIndexValue($object);
            $shouldInsert = $newpri != $prival;
        }

        if ($shouldInsert) {
            $this->insert($object, $meta);
        } else {
            $this->update($object, $meta);
        }

        event_after: {
            if (isset($meta->on['afterSave'])) {
                foreach ($meta->on['afterSave'] as $cb) { $cb = [$object, $cb]; $cb(); }
            }
            if (isset($this->on['afterSave'])) {
                foreach ($this->on['afterSave'] as $cb) { $cb($object, $meta); }
            }
        }
    }